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
12static 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_tso_bytes),
19	IONIC_LIF_STAT_DESC(tx_csum_none),
20	IONIC_LIF_STAT_DESC(tx_csum),
21	IONIC_LIF_STAT_DESC(rx_csum_none),
22	IONIC_LIF_STAT_DESC(rx_csum_complete),
23	IONIC_LIF_STAT_DESC(rx_csum_error),
24	IONIC_LIF_STAT_DESC(hw_tx_dropped),
25	IONIC_LIF_STAT_DESC(hw_rx_dropped),
26	IONIC_LIF_STAT_DESC(hw_rx_over_errors),
27	IONIC_LIF_STAT_DESC(hw_rx_missed_errors),
28	IONIC_LIF_STAT_DESC(hw_tx_aborted_errors),
29};
30
31static const struct ionic_stat_desc ionic_port_stats_desc[] = {
32	IONIC_PORT_STAT_DESC(frames_rx_ok),
33	IONIC_PORT_STAT_DESC(frames_rx_all),
34	IONIC_PORT_STAT_DESC(frames_rx_bad_fcs),
35	IONIC_PORT_STAT_DESC(frames_rx_bad_all),
36	IONIC_PORT_STAT_DESC(octets_rx_ok),
37	IONIC_PORT_STAT_DESC(octets_rx_all),
38	IONIC_PORT_STAT_DESC(frames_rx_unicast),
39	IONIC_PORT_STAT_DESC(frames_rx_multicast),
40	IONIC_PORT_STAT_DESC(frames_rx_broadcast),
41	IONIC_PORT_STAT_DESC(frames_rx_pause),
42	IONIC_PORT_STAT_DESC(frames_rx_bad_length),
43	IONIC_PORT_STAT_DESC(frames_rx_undersized),
44	IONIC_PORT_STAT_DESC(frames_rx_oversized),
45	IONIC_PORT_STAT_DESC(frames_rx_fragments),
46	IONIC_PORT_STAT_DESC(frames_rx_jabber),
47	IONIC_PORT_STAT_DESC(frames_rx_pripause),
48	IONIC_PORT_STAT_DESC(frames_rx_stomped_crc),
49	IONIC_PORT_STAT_DESC(frames_rx_too_long),
50	IONIC_PORT_STAT_DESC(frames_rx_vlan_good),
51	IONIC_PORT_STAT_DESC(frames_rx_dropped),
52	IONIC_PORT_STAT_DESC(frames_rx_less_than_64b),
53	IONIC_PORT_STAT_DESC(frames_rx_64b),
54	IONIC_PORT_STAT_DESC(frames_rx_65b_127b),
55	IONIC_PORT_STAT_DESC(frames_rx_128b_255b),
56	IONIC_PORT_STAT_DESC(frames_rx_256b_511b),
57	IONIC_PORT_STAT_DESC(frames_rx_512b_1023b),
58	IONIC_PORT_STAT_DESC(frames_rx_1024b_1518b),
59	IONIC_PORT_STAT_DESC(frames_rx_1519b_2047b),
60	IONIC_PORT_STAT_DESC(frames_rx_2048b_4095b),
61	IONIC_PORT_STAT_DESC(frames_rx_4096b_8191b),
62	IONIC_PORT_STAT_DESC(frames_rx_8192b_9215b),
63	IONIC_PORT_STAT_DESC(frames_rx_other),
64	IONIC_PORT_STAT_DESC(frames_tx_ok),
65	IONIC_PORT_STAT_DESC(frames_tx_all),
66	IONIC_PORT_STAT_DESC(frames_tx_bad),
67	IONIC_PORT_STAT_DESC(octets_tx_ok),
68	IONIC_PORT_STAT_DESC(octets_tx_total),
69	IONIC_PORT_STAT_DESC(frames_tx_unicast),
70	IONIC_PORT_STAT_DESC(frames_tx_multicast),
71	IONIC_PORT_STAT_DESC(frames_tx_broadcast),
72	IONIC_PORT_STAT_DESC(frames_tx_pause),
73	IONIC_PORT_STAT_DESC(frames_tx_pripause),
74	IONIC_PORT_STAT_DESC(frames_tx_vlan),
75	IONIC_PORT_STAT_DESC(frames_tx_less_than_64b),
76	IONIC_PORT_STAT_DESC(frames_tx_64b),
77	IONIC_PORT_STAT_DESC(frames_tx_65b_127b),
78	IONIC_PORT_STAT_DESC(frames_tx_128b_255b),
79	IONIC_PORT_STAT_DESC(frames_tx_256b_511b),
80	IONIC_PORT_STAT_DESC(frames_tx_512b_1023b),
81	IONIC_PORT_STAT_DESC(frames_tx_1024b_1518b),
82	IONIC_PORT_STAT_DESC(frames_tx_1519b_2047b),
83	IONIC_PORT_STAT_DESC(frames_tx_2048b_4095b),
84	IONIC_PORT_STAT_DESC(frames_tx_4096b_8191b),
85	IONIC_PORT_STAT_DESC(frames_tx_8192b_9215b),
86	IONIC_PORT_STAT_DESC(frames_tx_other),
87	IONIC_PORT_STAT_DESC(frames_tx_pri_0),
88	IONIC_PORT_STAT_DESC(frames_tx_pri_1),
89	IONIC_PORT_STAT_DESC(frames_tx_pri_2),
90	IONIC_PORT_STAT_DESC(frames_tx_pri_3),
91	IONIC_PORT_STAT_DESC(frames_tx_pri_4),
92	IONIC_PORT_STAT_DESC(frames_tx_pri_5),
93	IONIC_PORT_STAT_DESC(frames_tx_pri_6),
94	IONIC_PORT_STAT_DESC(frames_tx_pri_7),
95	IONIC_PORT_STAT_DESC(frames_rx_pri_0),
96	IONIC_PORT_STAT_DESC(frames_rx_pri_1),
97	IONIC_PORT_STAT_DESC(frames_rx_pri_2),
98	IONIC_PORT_STAT_DESC(frames_rx_pri_3),
99	IONIC_PORT_STAT_DESC(frames_rx_pri_4),
100	IONIC_PORT_STAT_DESC(frames_rx_pri_5),
101	IONIC_PORT_STAT_DESC(frames_rx_pri_6),
102	IONIC_PORT_STAT_DESC(frames_rx_pri_7),
103	IONIC_PORT_STAT_DESC(tx_pripause_0_1us_count),
104	IONIC_PORT_STAT_DESC(tx_pripause_1_1us_count),
105	IONIC_PORT_STAT_DESC(tx_pripause_2_1us_count),
106	IONIC_PORT_STAT_DESC(tx_pripause_3_1us_count),
107	IONIC_PORT_STAT_DESC(tx_pripause_4_1us_count),
108	IONIC_PORT_STAT_DESC(tx_pripause_5_1us_count),
109	IONIC_PORT_STAT_DESC(tx_pripause_6_1us_count),
110	IONIC_PORT_STAT_DESC(tx_pripause_7_1us_count),
111	IONIC_PORT_STAT_DESC(rx_pripause_0_1us_count),
112	IONIC_PORT_STAT_DESC(rx_pripause_1_1us_count),
113	IONIC_PORT_STAT_DESC(rx_pripause_2_1us_count),
114	IONIC_PORT_STAT_DESC(rx_pripause_3_1us_count),
115	IONIC_PORT_STAT_DESC(rx_pripause_4_1us_count),
116	IONIC_PORT_STAT_DESC(rx_pripause_5_1us_count),
117	IONIC_PORT_STAT_DESC(rx_pripause_6_1us_count),
118	IONIC_PORT_STAT_DESC(rx_pripause_7_1us_count),
119	IONIC_PORT_STAT_DESC(rx_pause_1us_count),
120	IONIC_PORT_STAT_DESC(frames_tx_truncated),
121};
122
123static const struct ionic_stat_desc ionic_tx_stats_desc[] = {
124	IONIC_TX_STAT_DESC(pkts),
125	IONIC_TX_STAT_DESC(bytes),
126	IONIC_TX_STAT_DESC(clean),
127	IONIC_TX_STAT_DESC(dma_map_err),
128	IONIC_TX_STAT_DESC(linearize),
129	IONIC_TX_STAT_DESC(frags),
130	IONIC_TX_STAT_DESC(tso),
131	IONIC_TX_STAT_DESC(tso_bytes),
132	IONIC_TX_STAT_DESC(csum_none),
133	IONIC_TX_STAT_DESC(csum),
134	IONIC_TX_STAT_DESC(vlan_inserted),
135};
136
137static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
138	IONIC_RX_STAT_DESC(pkts),
139	IONIC_RX_STAT_DESC(bytes),
140	IONIC_RX_STAT_DESC(dma_map_err),
141	IONIC_RX_STAT_DESC(alloc_err),
142	IONIC_RX_STAT_DESC(csum_none),
143	IONIC_RX_STAT_DESC(csum_complete),
144	IONIC_RX_STAT_DESC(csum_error),
145	IONIC_RX_STAT_DESC(dropped),
146	IONIC_RX_STAT_DESC(vlan_stripped),
147};
148
149static const struct ionic_stat_desc ionic_txq_stats_desc[] = {
150	IONIC_TX_Q_STAT_DESC(stop),
151	IONIC_TX_Q_STAT_DESC(wake),
152	IONIC_TX_Q_STAT_DESC(drop),
153	IONIC_TX_Q_STAT_DESC(dbell_count),
154};
155
156static const struct ionic_stat_desc ionic_dbg_cq_stats_desc[] = {
157	IONIC_CQ_STAT_DESC(compl_count),
158};
159
160static const struct ionic_stat_desc ionic_dbg_intr_stats_desc[] = {
161	IONIC_INTR_STAT_DESC(rearm_count),
162};
163
164static const struct ionic_stat_desc ionic_dbg_napi_stats_desc[] = {
165	IONIC_NAPI_STAT_DESC(poll_count),
166};
167
168#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
169#define IONIC_NUM_PORT_STATS ARRAY_SIZE(ionic_port_stats_desc)
170#define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc)
171#define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc)
172#define IONIC_NUM_TX_Q_STATS ARRAY_SIZE(ionic_txq_stats_desc)
173#define IONIC_NUM_DBG_CQ_STATS ARRAY_SIZE(ionic_dbg_cq_stats_desc)
174#define IONIC_NUM_DBG_INTR_STATS ARRAY_SIZE(ionic_dbg_intr_stats_desc)
175#define IONIC_NUM_DBG_NAPI_STATS ARRAY_SIZE(ionic_dbg_napi_stats_desc)
176
177#define MAX_Q(lif)   ((lif)->netdev->real_num_tx_queues)
178
179static void ionic_get_lif_stats(struct ionic_lif *lif,
180				struct ionic_lif_sw_stats *stats)
181{
182	struct ionic_tx_stats *txstats;
183	struct ionic_rx_stats *rxstats;
184	struct rtnl_link_stats64 ns;
185	int q_num;
186
187	memset(stats, 0, sizeof(*stats));
188
189	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
190		txstats = &lif->txqstats[q_num];
191		stats->tx_packets += txstats->pkts;
192		stats->tx_bytes += txstats->bytes;
193		stats->tx_tso += txstats->tso;
194		stats->tx_tso_bytes += txstats->tso_bytes;
195		stats->tx_csum_none += txstats->csum_none;
196		stats->tx_csum += txstats->csum;
197
198		rxstats = &lif->rxqstats[q_num];
199		stats->rx_packets += rxstats->pkts;
200		stats->rx_bytes += rxstats->bytes;
201		stats->rx_csum_none += rxstats->csum_none;
202		stats->rx_csum_complete += rxstats->csum_complete;
203		stats->rx_csum_error += rxstats->csum_error;
204	}
205
206	ionic_get_stats64(lif->netdev, &ns);
207	stats->hw_tx_dropped = ns.tx_dropped;
208	stats->hw_rx_dropped = ns.rx_dropped;
209	stats->hw_rx_over_errors = ns.rx_over_errors;
210	stats->hw_rx_missed_errors = ns.rx_missed_errors;
211	stats->hw_tx_aborted_errors = ns.tx_aborted_errors;
212}
213
214static u64 ionic_sw_stats_get_count(struct ionic_lif *lif)
215{
216	u64 total = 0;
217
218	/* lif stats */
219	total += IONIC_NUM_LIF_STATS;
220
221	/* tx stats */
222	total += MAX_Q(lif) * IONIC_NUM_TX_STATS;
223
224	/* rx stats */
225	total += MAX_Q(lif) * IONIC_NUM_RX_STATS;
226
227	/* port stats */
228	total += IONIC_NUM_PORT_STATS;
229
230	if (test_bit(IONIC_LIF_F_UP, lif->state) &&
231	    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
232		/* tx debug stats */
233		total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS +
234				      IONIC_NUM_TX_Q_STATS +
235				      IONIC_NUM_DBG_INTR_STATS +
236				      IONIC_MAX_NUM_SG_CNTR);
237
238		/* rx debug stats */
239		total += MAX_Q(lif) * (IONIC_NUM_DBG_CQ_STATS +
240				      IONIC_NUM_DBG_INTR_STATS +
241				      IONIC_NUM_DBG_NAPI_STATS +
242				      IONIC_MAX_NUM_NAPI_CNTR);
243	}
244
245	return total;
246}
247
248static void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf)
249{
250	int i, q_num;
251
252	for (i = 0; i < IONIC_NUM_LIF_STATS; i++) {
253		snprintf(*buf, ETH_GSTRING_LEN, ionic_lif_stats_desc[i].name);
254		*buf += ETH_GSTRING_LEN;
255	}
256
257	for (i = 0; i < IONIC_NUM_PORT_STATS; i++) {
258		snprintf(*buf, ETH_GSTRING_LEN,
259			 ionic_port_stats_desc[i].name);
260		*buf += ETH_GSTRING_LEN;
261	}
262
263	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
264		for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
265			snprintf(*buf, ETH_GSTRING_LEN, "tx_%d_%s",
266				 q_num, ionic_tx_stats_desc[i].name);
267			*buf += ETH_GSTRING_LEN;
268		}
269
270		if (test_bit(IONIC_LIF_F_UP, lif->state) &&
271		    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
272			for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) {
273				snprintf(*buf, ETH_GSTRING_LEN,
274					 "txq_%d_%s",
275					 q_num,
276					 ionic_txq_stats_desc[i].name);
277				*buf += ETH_GSTRING_LEN;
278			}
279			for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
280				snprintf(*buf, ETH_GSTRING_LEN,
281					 "txq_%d_cq_%s",
282					 q_num,
283					 ionic_dbg_cq_stats_desc[i].name);
284				*buf += ETH_GSTRING_LEN;
285			}
286			for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
287				snprintf(*buf, ETH_GSTRING_LEN,
288					 "txq_%d_intr_%s",
289					 q_num,
290					 ionic_dbg_intr_stats_desc[i].name);
291				*buf += ETH_GSTRING_LEN;
292			}
293			for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) {
294				snprintf(*buf, ETH_GSTRING_LEN,
295					 "txq_%d_sg_cntr_%d",
296					 q_num, i);
297				*buf += ETH_GSTRING_LEN;
298			}
299		}
300	}
301	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
302		for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
303			snprintf(*buf, ETH_GSTRING_LEN,
304				 "rx_%d_%s",
305				 q_num, ionic_rx_stats_desc[i].name);
306			*buf += ETH_GSTRING_LEN;
307		}
308
309		if (test_bit(IONIC_LIF_F_UP, lif->state) &&
310		    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
311			for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
312				snprintf(*buf, ETH_GSTRING_LEN,
313					 "rxq_%d_cq_%s",
314					 q_num,
315					 ionic_dbg_cq_stats_desc[i].name);
316				*buf += ETH_GSTRING_LEN;
317			}
318			for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
319				snprintf(*buf, ETH_GSTRING_LEN,
320					 "rxq_%d_intr_%s",
321					 q_num,
322					 ionic_dbg_intr_stats_desc[i].name);
323				*buf += ETH_GSTRING_LEN;
324			}
325			for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) {
326				snprintf(*buf, ETH_GSTRING_LEN,
327					 "rxq_%d_napi_%s",
328					 q_num,
329					 ionic_dbg_napi_stats_desc[i].name);
330				*buf += ETH_GSTRING_LEN;
331			}
332			for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) {
333				snprintf(*buf, ETH_GSTRING_LEN,
334					 "rxq_%d_napi_work_done_%d",
335					 q_num, i);
336				*buf += ETH_GSTRING_LEN;
337			}
338		}
339	}
340}
341
342static void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
343{
344	struct ionic_port_stats *port_stats;
345	struct ionic_lif_sw_stats lif_stats;
346	struct ionic_qcq *txqcq, *rxqcq;
347	struct ionic_tx_stats *txstats;
348	struct ionic_rx_stats *rxstats;
349	int i, q_num;
350
351	ionic_get_lif_stats(lif, &lif_stats);
352
353	for (i = 0; i < IONIC_NUM_LIF_STATS; i++) {
354		**buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]);
355		(*buf)++;
356	}
357
358	port_stats = &lif->ionic->idev.port_info->stats;
359	for (i = 0; i < IONIC_NUM_PORT_STATS; i++) {
360		**buf = IONIC_READ_STAT_LE64(port_stats,
361					     &ionic_port_stats_desc[i]);
362		(*buf)++;
363	}
364
365	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
366		txstats = &lif->txqstats[q_num];
367
368		for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
369			**buf = IONIC_READ_STAT64(txstats,
370						  &ionic_tx_stats_desc[i]);
371			(*buf)++;
372		}
373
374		if (test_bit(IONIC_LIF_F_UP, lif->state) &&
375		    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
376			txqcq = lif->txqcqs[q_num];
377			for (i = 0; i < IONIC_NUM_TX_Q_STATS; i++) {
378				**buf = IONIC_READ_STAT64(&txqcq->q,
379						      &ionic_txq_stats_desc[i]);
380				(*buf)++;
381			}
382			for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
383				**buf = IONIC_READ_STAT64(&txqcq->cq,
384						   &ionic_dbg_cq_stats_desc[i]);
385				(*buf)++;
386			}
387			for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
388				**buf = IONIC_READ_STAT64(&txqcq->intr,
389						 &ionic_dbg_intr_stats_desc[i]);
390				(*buf)++;
391			}
392			for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) {
393				**buf = txstats->sg_cntr[i];
394				(*buf)++;
395			}
396		}
397	}
398
399	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
400		rxstats = &lif->rxqstats[q_num];
401
402		for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
403			**buf = IONIC_READ_STAT64(rxstats,
404						  &ionic_rx_stats_desc[i]);
405			(*buf)++;
406		}
407
408		if (test_bit(IONIC_LIF_F_UP, lif->state) &&
409		    test_bit(IONIC_LIF_F_SW_DEBUG_STATS, lif->state)) {
410			rxqcq = lif->rxqcqs[q_num];
411			for (i = 0; i < IONIC_NUM_DBG_CQ_STATS; i++) {
412				**buf = IONIC_READ_STAT64(&rxqcq->cq,
413						   &ionic_dbg_cq_stats_desc[i]);
414				(*buf)++;
415			}
416			for (i = 0; i < IONIC_NUM_DBG_INTR_STATS; i++) {
417				**buf = IONIC_READ_STAT64(&rxqcq->intr,
418						 &ionic_dbg_intr_stats_desc[i]);
419				(*buf)++;
420			}
421			for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) {
422				**buf = IONIC_READ_STAT64(&rxqcq->napi_stats,
423						 &ionic_dbg_napi_stats_desc[i]);
424				(*buf)++;
425			}
426			for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) {
427				**buf = rxqcq->napi_stats.work_done_cntr[i];
428				(*buf)++;
429			}
430		}
431	}
432}
433
434const struct ionic_stats_group_intf ionic_stats_groups[] = {
435	/* SW Stats group */
436	{
437		.get_strings = ionic_sw_stats_get_strings,
438		.get_values = ionic_sw_stats_get_values,
439		.get_count = ionic_sw_stats_get_count,
440	},
441	/* Add more stat groups here */
442};
443
444const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups);
445