162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/ethtool.h>
562306a36Sopenharmony_ci#include <linux/kernel.h>
662306a36Sopenharmony_ci#include <linux/mutex.h>
762306a36Sopenharmony_ci#include <linux/netdevice.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "ionic.h"
1062306a36Sopenharmony_ci#include "ionic_lif.h"
1162306a36Sopenharmony_ci#include "ionic_stats.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic const struct ionic_stat_desc ionic_lif_stats_desc[] = {
1462306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_packets),
1562306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_bytes),
1662306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(rx_packets),
1762306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(rx_bytes),
1862306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_tso),
1962306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_tso_bytes),
2062306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_csum_none),
2162306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(tx_csum),
2262306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(rx_csum_none),
2362306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(rx_csum_complete),
2462306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(rx_csum_error),
2562306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(hw_tx_dropped),
2662306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(hw_rx_dropped),
2762306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(hw_rx_over_errors),
2862306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(hw_rx_missed_errors),
2962306a36Sopenharmony_ci	IONIC_LIF_STAT_DESC(hw_tx_aborted_errors),
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic const struct ionic_stat_desc ionic_port_stats_desc[] = {
3362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_ok),
3462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_all),
3562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_bad_fcs),
3662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_bad_all),
3762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(octets_rx_ok),
3862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(octets_rx_all),
3962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_unicast),
4062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_multicast),
4162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_broadcast),
4262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pause),
4362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_bad_length),
4462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_undersized),
4562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_oversized),
4662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_fragments),
4762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_jabber),
4862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pripause),
4962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_stomped_crc),
5062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_too_long),
5162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_vlan_good),
5262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_dropped),
5362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_less_than_64b),
5462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_64b),
5562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_65b_127b),
5662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_128b_255b),
5762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_256b_511b),
5862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_512b_1023b),
5962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_1024b_1518b),
6062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_1519b_2047b),
6162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_2048b_4095b),
6262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_4096b_8191b),
6362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_8192b_9215b),
6462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_other),
6562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_ok),
6662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_all),
6762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_bad),
6862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(octets_tx_ok),
6962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(octets_tx_total),
7062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_unicast),
7162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_multicast),
7262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_broadcast),
7362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pause),
7462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pripause),
7562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_vlan),
7662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_less_than_64b),
7762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_64b),
7862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_65b_127b),
7962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_128b_255b),
8062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_256b_511b),
8162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_512b_1023b),
8262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_1024b_1518b),
8362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_1519b_2047b),
8462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_2048b_4095b),
8562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_4096b_8191b),
8662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_8192b_9215b),
8762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_other),
8862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_0),
8962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_1),
9062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_2),
9162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_3),
9262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_4),
9362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_5),
9462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_6),
9562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_pri_7),
9662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_0),
9762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_1),
9862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_2),
9962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_3),
10062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_4),
10162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_5),
10262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_6),
10362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_rx_pri_7),
10462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_0_1us_count),
10562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_1_1us_count),
10662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_2_1us_count),
10762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_3_1us_count),
10862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_4_1us_count),
10962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_5_1us_count),
11062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_6_1us_count),
11162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(tx_pripause_7_1us_count),
11262306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_0_1us_count),
11362306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_1_1us_count),
11462306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_2_1us_count),
11562306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_3_1us_count),
11662306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_4_1us_count),
11762306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_5_1us_count),
11862306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_6_1us_count),
11962306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pripause_7_1us_count),
12062306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(rx_pause_1us_count),
12162306a36Sopenharmony_ci	IONIC_PORT_STAT_DESC(frames_tx_truncated),
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic const struct ionic_stat_desc ionic_tx_stats_desc[] = {
12562306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(pkts),
12662306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(bytes),
12762306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(clean),
12862306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(dma_map_err),
12962306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(linearize),
13062306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(frags),
13162306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(tso),
13262306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(tso_bytes),
13362306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(hwstamp_valid),
13462306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(hwstamp_invalid),
13562306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(csum_none),
13662306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(csum),
13762306a36Sopenharmony_ci	IONIC_TX_STAT_DESC(vlan_inserted),
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic const struct ionic_stat_desc ionic_rx_stats_desc[] = {
14162306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(pkts),
14262306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(bytes),
14362306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(dma_map_err),
14462306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(alloc_err),
14562306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(csum_none),
14662306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(csum_complete),
14762306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(csum_error),
14862306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(hwstamp_valid),
14962306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(hwstamp_invalid),
15062306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(dropped),
15162306a36Sopenharmony_ci	IONIC_RX_STAT_DESC(vlan_stripped),
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
15562306a36Sopenharmony_ci#define IONIC_NUM_PORT_STATS ARRAY_SIZE(ionic_port_stats_desc)
15662306a36Sopenharmony_ci#define IONIC_NUM_TX_STATS ARRAY_SIZE(ionic_tx_stats_desc)
15762306a36Sopenharmony_ci#define IONIC_NUM_RX_STATS ARRAY_SIZE(ionic_rx_stats_desc)
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci#define MAX_Q(lif)   ((lif)->netdev->real_num_tx_queues)
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic void ionic_add_lif_txq_stats(struct ionic_lif *lif, int q_num,
16262306a36Sopenharmony_ci				    struct ionic_lif_sw_stats *stats)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct ionic_tx_stats *txstats = &lif->txqstats[q_num];
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	stats->tx_packets += txstats->pkts;
16762306a36Sopenharmony_ci	stats->tx_bytes += txstats->bytes;
16862306a36Sopenharmony_ci	stats->tx_tso += txstats->tso;
16962306a36Sopenharmony_ci	stats->tx_tso_bytes += txstats->tso_bytes;
17062306a36Sopenharmony_ci	stats->tx_csum_none += txstats->csum_none;
17162306a36Sopenharmony_ci	stats->tx_csum += txstats->csum;
17262306a36Sopenharmony_ci	stats->tx_hwstamp_valid += txstats->hwstamp_valid;
17362306a36Sopenharmony_ci	stats->tx_hwstamp_invalid += txstats->hwstamp_invalid;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num,
17762306a36Sopenharmony_ci				    struct ionic_lif_sw_stats *stats)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	struct ionic_rx_stats *rxstats = &lif->rxqstats[q_num];
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	stats->rx_packets += rxstats->pkts;
18262306a36Sopenharmony_ci	stats->rx_bytes += rxstats->bytes;
18362306a36Sopenharmony_ci	stats->rx_csum_none += rxstats->csum_none;
18462306a36Sopenharmony_ci	stats->rx_csum_complete += rxstats->csum_complete;
18562306a36Sopenharmony_ci	stats->rx_csum_error += rxstats->csum_error;
18662306a36Sopenharmony_ci	stats->rx_hwstamp_valid += rxstats->hwstamp_valid;
18762306a36Sopenharmony_ci	stats->rx_hwstamp_invalid += rxstats->hwstamp_invalid;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic void ionic_get_lif_stats(struct ionic_lif *lif,
19162306a36Sopenharmony_ci				struct ionic_lif_sw_stats *stats)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	struct rtnl_link_stats64 ns;
19462306a36Sopenharmony_ci	int q_num;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	memset(stats, 0, sizeof(*stats));
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	for (q_num = 0; q_num < MAX_Q(lif); q_num++) {
19962306a36Sopenharmony_ci		ionic_add_lif_txq_stats(lif, q_num, stats);
20062306a36Sopenharmony_ci		ionic_add_lif_rxq_stats(lif, q_num, stats);
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	if (lif->hwstamp_txq)
20462306a36Sopenharmony_ci		ionic_add_lif_txq_stats(lif, lif->hwstamp_txq->q.index, stats);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (lif->hwstamp_rxq)
20762306a36Sopenharmony_ci		ionic_add_lif_rxq_stats(lif, lif->hwstamp_rxq->q.index, stats);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	ionic_get_stats64(lif->netdev, &ns);
21062306a36Sopenharmony_ci	stats->hw_tx_dropped = ns.tx_dropped;
21162306a36Sopenharmony_ci	stats->hw_rx_dropped = ns.rx_dropped;
21262306a36Sopenharmony_ci	stats->hw_rx_over_errors = ns.rx_over_errors;
21362306a36Sopenharmony_ci	stats->hw_rx_missed_errors = ns.rx_missed_errors;
21462306a36Sopenharmony_ci	stats->hw_tx_aborted_errors = ns.tx_aborted_errors;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic u64 ionic_sw_stats_get_count(struct ionic_lif *lif)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	u64 total = 0, tx_queues = MAX_Q(lif), rx_queues = MAX_Q(lif);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	if (lif->hwstamp_txq)
22262306a36Sopenharmony_ci		tx_queues += 1;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (lif->hwstamp_rxq)
22562306a36Sopenharmony_ci		rx_queues += 1;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	total += IONIC_NUM_LIF_STATS;
22862306a36Sopenharmony_ci	total += IONIC_NUM_PORT_STATS;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	total += tx_queues * IONIC_NUM_TX_STATS;
23162306a36Sopenharmony_ci	total += rx_queues * IONIC_NUM_RX_STATS;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	return total;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic void ionic_sw_stats_get_tx_strings(struct ionic_lif *lif, u8 **buf,
23762306a36Sopenharmony_ci					  int q_num)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	int i;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_TX_STATS; i++)
24262306a36Sopenharmony_ci		ethtool_sprintf(buf, "tx_%d_%s", q_num,
24362306a36Sopenharmony_ci				ionic_tx_stats_desc[i].name);
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic void ionic_sw_stats_get_rx_strings(struct ionic_lif *lif, u8 **buf,
24762306a36Sopenharmony_ci					  int q_num)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	int i;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_RX_STATS; i++)
25262306a36Sopenharmony_ci		ethtool_sprintf(buf, "rx_%d_%s", q_num,
25362306a36Sopenharmony_ci				ionic_rx_stats_desc[i].name);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic void ionic_sw_stats_get_strings(struct ionic_lif *lif, u8 **buf)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	int i, q_num;
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_LIF_STATS; i++)
26162306a36Sopenharmony_ci		ethtool_sprintf(buf, ionic_lif_stats_desc[i].name);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_PORT_STATS; i++)
26462306a36Sopenharmony_ci		ethtool_sprintf(buf, ionic_port_stats_desc[i].name);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	for (q_num = 0; q_num < MAX_Q(lif); q_num++)
26762306a36Sopenharmony_ci		ionic_sw_stats_get_tx_strings(lif, buf, q_num);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	if (lif->hwstamp_txq)
27062306a36Sopenharmony_ci		ionic_sw_stats_get_tx_strings(lif, buf, lif->hwstamp_txq->q.index);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	for (q_num = 0; q_num < MAX_Q(lif); q_num++)
27362306a36Sopenharmony_ci		ionic_sw_stats_get_rx_strings(lif, buf, q_num);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (lif->hwstamp_rxq)
27662306a36Sopenharmony_ci		ionic_sw_stats_get_rx_strings(lif, buf, lif->hwstamp_rxq->q.index);
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf,
28062306a36Sopenharmony_ci					  int q_num)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct ionic_tx_stats *txstats;
28362306a36Sopenharmony_ci	int i;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	txstats = &lif->txqstats[q_num];
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_TX_STATS; i++) {
28862306a36Sopenharmony_ci		**buf = IONIC_READ_STAT64(txstats, &ionic_tx_stats_desc[i]);
28962306a36Sopenharmony_ci		(*buf)++;
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_cistatic void ionic_sw_stats_get_rxq_values(struct ionic_lif *lif, u64 **buf,
29462306a36Sopenharmony_ci					  int q_num)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct ionic_rx_stats *rxstats;
29762306a36Sopenharmony_ci	int i;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	rxstats = &lif->rxqstats[q_num];
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_RX_STATS; i++) {
30262306a36Sopenharmony_ci		**buf = IONIC_READ_STAT64(rxstats, &ionic_rx_stats_desc[i]);
30362306a36Sopenharmony_ci		(*buf)++;
30462306a36Sopenharmony_ci	}
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic void ionic_sw_stats_get_values(struct ionic_lif *lif, u64 **buf)
30862306a36Sopenharmony_ci{
30962306a36Sopenharmony_ci	struct ionic_port_stats *port_stats;
31062306a36Sopenharmony_ci	struct ionic_lif_sw_stats lif_stats;
31162306a36Sopenharmony_ci	int i, q_num;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	ionic_get_lif_stats(lif, &lif_stats);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_LIF_STATS; i++) {
31662306a36Sopenharmony_ci		**buf = IONIC_READ_STAT64(&lif_stats, &ionic_lif_stats_desc[i]);
31762306a36Sopenharmony_ci		(*buf)++;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	port_stats = &lif->ionic->idev.port_info->stats;
32162306a36Sopenharmony_ci	for (i = 0; i < IONIC_NUM_PORT_STATS; i++) {
32262306a36Sopenharmony_ci		**buf = IONIC_READ_STAT_LE64(port_stats,
32362306a36Sopenharmony_ci					     &ionic_port_stats_desc[i]);
32462306a36Sopenharmony_ci		(*buf)++;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	for (q_num = 0; q_num < MAX_Q(lif); q_num++)
32862306a36Sopenharmony_ci		ionic_sw_stats_get_txq_values(lif, buf, q_num);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (lif->hwstamp_txq)
33162306a36Sopenharmony_ci		ionic_sw_stats_get_txq_values(lif, buf, lif->hwstamp_txq->q.index);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	for (q_num = 0; q_num < MAX_Q(lif); q_num++)
33462306a36Sopenharmony_ci		ionic_sw_stats_get_rxq_values(lif, buf, q_num);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (lif->hwstamp_rxq)
33762306a36Sopenharmony_ci		ionic_sw_stats_get_rxq_values(lif, buf, lif->hwstamp_rxq->q.index);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ciconst struct ionic_stats_group_intf ionic_stats_groups[] = {
34162306a36Sopenharmony_ci	/* SW Stats group */
34262306a36Sopenharmony_ci	{
34362306a36Sopenharmony_ci		.get_strings = ionic_sw_stats_get_strings,
34462306a36Sopenharmony_ci		.get_values = ionic_sw_stats_get_values,
34562306a36Sopenharmony_ci		.get_count = ionic_sw_stats_get_count,
34662306a36Sopenharmony_ci	},
34762306a36Sopenharmony_ci	/* Add more stat groups here */
34862306a36Sopenharmony_ci};
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ciconst int ionic_num_stats_grps = ARRAY_SIZE(ionic_stats_groups);
351