Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  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_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
 25static 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
 34static 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
 44static 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
 51static const struct ionic_stat_desc ionic_dbg_cq_stats_desc[] = {
 52	IONIC_CQ_STAT_DESC(compl_count),
 53};
 54
 55static const struct ionic_stat_desc ionic_dbg_intr_stats_desc[] = {
 56	IONIC_INTR_STAT_DESC(rearm_count),
 57};
 58
 59static 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
 73static 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
107static 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
138static 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
225static 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
309const 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
319const int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups);