xref: /dpdk/drivers/net/mlx5/mlx5_stats.c (revision d5b0924ba6baae2cb6ac7c880db0977d4befedc6)
187011737SAdrien Mazarguil /*-
287011737SAdrien Mazarguil  *   BSD LICENSE
387011737SAdrien Mazarguil  *
487011737SAdrien Mazarguil  *   Copyright 2015 6WIND S.A.
587011737SAdrien Mazarguil  *   Copyright 2015 Mellanox.
687011737SAdrien Mazarguil  *
787011737SAdrien Mazarguil  *   Redistribution and use in source and binary forms, with or without
887011737SAdrien Mazarguil  *   modification, are permitted provided that the following conditions
987011737SAdrien Mazarguil  *   are met:
1087011737SAdrien Mazarguil  *
1187011737SAdrien Mazarguil  *     * Redistributions of source code must retain the above copyright
1287011737SAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer.
1387011737SAdrien Mazarguil  *     * Redistributions in binary form must reproduce the above copyright
1487011737SAdrien Mazarguil  *       notice, this list of conditions and the following disclaimer in
1587011737SAdrien Mazarguil  *       the documentation and/or other materials provided with the
1687011737SAdrien Mazarguil  *       distribution.
1787011737SAdrien Mazarguil  *     * Neither the name of 6WIND S.A. nor the names of its
1887011737SAdrien Mazarguil  *       contributors may be used to endorse or promote products derived
1987011737SAdrien Mazarguil  *       from this software without specific prior written permission.
2087011737SAdrien Mazarguil  *
2187011737SAdrien Mazarguil  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2287011737SAdrien Mazarguil  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2387011737SAdrien Mazarguil  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2487011737SAdrien Mazarguil  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2587011737SAdrien Mazarguil  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2687011737SAdrien Mazarguil  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2787011737SAdrien Mazarguil  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2887011737SAdrien Mazarguil  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2987011737SAdrien Mazarguil  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3087011737SAdrien Mazarguil  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3187011737SAdrien Mazarguil  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3287011737SAdrien Mazarguil  */
3387011737SAdrien Mazarguil 
34a4193ae3SShahaf Shuler #include <linux/sockios.h>
35a4193ae3SShahaf Shuler #include <linux/ethtool.h>
36a4193ae3SShahaf Shuler 
3787011737SAdrien Mazarguil #include <rte_ethdev.h>
38a4193ae3SShahaf Shuler #include <rte_common.h>
39a4193ae3SShahaf Shuler #include <rte_malloc.h>
4087011737SAdrien Mazarguil 
4187011737SAdrien Mazarguil #include "mlx5.h"
4287011737SAdrien Mazarguil #include "mlx5_rxtx.h"
4387011737SAdrien Mazarguil #include "mlx5_defs.h"
4487011737SAdrien Mazarguil 
45a4193ae3SShahaf Shuler struct mlx5_counter_ctrl {
46a4193ae3SShahaf Shuler 	/* Name of the counter. */
47a4193ae3SShahaf Shuler 	char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
48a4193ae3SShahaf Shuler 	/* Name of the counter on the device table. */
49a4193ae3SShahaf Shuler 	char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
50a4193ae3SShahaf Shuler };
51a4193ae3SShahaf Shuler 
52a4193ae3SShahaf Shuler static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
53a4193ae3SShahaf Shuler 	{
54a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_unicast_bytes",
55a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_unicast_bytes",
56a4193ae3SShahaf Shuler 	},
57a4193ae3SShahaf Shuler 	{
58a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_multicast_bytes",
59a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_multicast_bytes",
60a4193ae3SShahaf Shuler 	},
61a4193ae3SShahaf Shuler 	{
62a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_broadcast_bytes",
63a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_broadcast_bytes",
64a4193ae3SShahaf Shuler 	},
65a4193ae3SShahaf Shuler 	{
66a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_unicast_packets",
67a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_unicast_packets",
68a4193ae3SShahaf Shuler 	},
69a4193ae3SShahaf Shuler 	{
70a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_multicast_packets",
71a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_multicast_packets",
72a4193ae3SShahaf Shuler 	},
73a4193ae3SShahaf Shuler 	{
74a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_broadcast_packets",
75a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_broadcast_packets",
76a4193ae3SShahaf Shuler 	},
77a4193ae3SShahaf Shuler 	{
78a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_unicast_bytes",
79a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_unicast_bytes",
80a4193ae3SShahaf Shuler 	},
81a4193ae3SShahaf Shuler 	{
82a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_multicast_bytes",
83a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_multicast_bytes",
84a4193ae3SShahaf Shuler 	},
85a4193ae3SShahaf Shuler 	{
86a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_broadcast_bytes",
87a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_broadcast_bytes",
88a4193ae3SShahaf Shuler 	},
89a4193ae3SShahaf Shuler 	{
90a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_unicast_packets",
91a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_unicast_packets",
92a4193ae3SShahaf Shuler 	},
93a4193ae3SShahaf Shuler 	{
94a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_multicast_packets",
95a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_multicast_packets",
96a4193ae3SShahaf Shuler 	},
97a4193ae3SShahaf Shuler 	{
98a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_broadcast_packets",
99a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_broadcast_packets",
100a4193ae3SShahaf Shuler 	},
101a4193ae3SShahaf Shuler 	{
102a4193ae3SShahaf Shuler 		.dpdk_name = "rx_wqe_err",
103a4193ae3SShahaf Shuler 		.ctr_name = "rx_wqe_err",
104a4193ae3SShahaf Shuler 	},
105a4193ae3SShahaf Shuler 	{
106a4193ae3SShahaf Shuler 		.dpdk_name = "rx_crc_errors_phy",
107a4193ae3SShahaf Shuler 		.ctr_name = "rx_crc_errors_phy",
108a4193ae3SShahaf Shuler 	},
109a4193ae3SShahaf Shuler 	{
110a4193ae3SShahaf Shuler 		.dpdk_name = "rx_in_range_len_errors_phy",
111a4193ae3SShahaf Shuler 		.ctr_name = "rx_in_range_len_errors_phy",
112a4193ae3SShahaf Shuler 	},
113a4193ae3SShahaf Shuler 	{
114a4193ae3SShahaf Shuler 		.dpdk_name = "rx_symbol_err_phy",
115a4193ae3SShahaf Shuler 		.ctr_name = "rx_symbol_err_phy",
116a4193ae3SShahaf Shuler 	},
117a4193ae3SShahaf Shuler 	{
118a4193ae3SShahaf Shuler 		.dpdk_name = "tx_errors_phy",
119a4193ae3SShahaf Shuler 		.ctr_name = "tx_errors_phy",
120a4193ae3SShahaf Shuler 	},
121859081d3SShahaf Shuler 	{
122859081d3SShahaf Shuler 		.dpdk_name = "rx_out_of_buffer",
123859081d3SShahaf Shuler 		.ctr_name = "out_of_buffer",
124859081d3SShahaf Shuler 	},
125a4193ae3SShahaf Shuler };
126a4193ae3SShahaf Shuler 
127a4193ae3SShahaf Shuler static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
128a4193ae3SShahaf Shuler 
129a4193ae3SShahaf Shuler /**
130a4193ae3SShahaf Shuler  * Read device counters table.
131a4193ae3SShahaf Shuler  *
132a4193ae3SShahaf Shuler  * @param priv
133a4193ae3SShahaf Shuler  *   Pointer to private structure.
134a4193ae3SShahaf Shuler  * @param[out] stats
135a4193ae3SShahaf Shuler  *   Counters table output buffer.
136a4193ae3SShahaf Shuler  *
137a4193ae3SShahaf Shuler  * @return
138a4193ae3SShahaf Shuler  *   0 on success and stats is filled, negative on error.
139a4193ae3SShahaf Shuler  */
140a4193ae3SShahaf Shuler static int
141a4193ae3SShahaf Shuler priv_read_dev_counters(struct priv *priv, uint64_t *stats)
142a4193ae3SShahaf Shuler {
143a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
144a4193ae3SShahaf Shuler 	unsigned int i;
145a4193ae3SShahaf Shuler 	struct ifreq ifr;
146a4193ae3SShahaf Shuler 	unsigned int stats_sz = (xstats_ctrl->stats_n * sizeof(uint64_t)) +
147a4193ae3SShahaf Shuler 				 sizeof(struct ethtool_stats);
148a4193ae3SShahaf Shuler 	struct ethtool_stats et_stats[(stats_sz + (
149a4193ae3SShahaf Shuler 				      sizeof(struct ethtool_stats) - 1)) /
150a4193ae3SShahaf Shuler 				      sizeof(struct ethtool_stats)];
151a4193ae3SShahaf Shuler 
152a4193ae3SShahaf Shuler 	et_stats->cmd = ETHTOOL_GSTATS;
153a4193ae3SShahaf Shuler 	et_stats->n_stats = xstats_ctrl->stats_n;
154a4193ae3SShahaf Shuler 	ifr.ifr_data = (caddr_t)et_stats;
155a4193ae3SShahaf Shuler 	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
156a4193ae3SShahaf Shuler 		WARN("unable to read statistic values from device");
157a4193ae3SShahaf Shuler 		return -1;
158a4193ae3SShahaf Shuler 	}
159859081d3SShahaf Shuler 	for (i = 0; i != xstats_n; ++i) {
160859081d3SShahaf Shuler 		if (priv_is_ib_cntr(mlx5_counters_init[i].ctr_name))
161859081d3SShahaf Shuler 			priv_get_cntr_sysfs(priv,
162859081d3SShahaf Shuler 					    mlx5_counters_init[i].ctr_name,
163859081d3SShahaf Shuler 					    &stats[i]);
164859081d3SShahaf Shuler 		else
165a4193ae3SShahaf Shuler 			stats[i] = (uint64_t)
166a4193ae3SShahaf Shuler 				et_stats->data[xstats_ctrl->dev_table_idx[i]];
167859081d3SShahaf Shuler 	}
168a4193ae3SShahaf Shuler 	return 0;
169a4193ae3SShahaf Shuler }
170a4193ae3SShahaf Shuler 
171a4193ae3SShahaf Shuler /**
172e62bc9e7SShahaf Shuler  * Query the number of statistics provided by ETHTOOL.
173e62bc9e7SShahaf Shuler  *
174e62bc9e7SShahaf Shuler  * @param priv
175e62bc9e7SShahaf Shuler  *   Pointer to private structure.
176e62bc9e7SShahaf Shuler  *
177e62bc9e7SShahaf Shuler  * @return
178e62bc9e7SShahaf Shuler  *   Number of statistics on success, -1 on error.
179e62bc9e7SShahaf Shuler  */
180e62bc9e7SShahaf Shuler static int
181e62bc9e7SShahaf Shuler priv_ethtool_get_stats_n(struct priv *priv) {
182e62bc9e7SShahaf Shuler 	struct ethtool_drvinfo drvinfo;
183e62bc9e7SShahaf Shuler 	struct ifreq ifr;
184e62bc9e7SShahaf Shuler 
185e62bc9e7SShahaf Shuler 	drvinfo.cmd = ETHTOOL_GDRVINFO;
186e62bc9e7SShahaf Shuler 	ifr.ifr_data = (caddr_t)&drvinfo;
187e62bc9e7SShahaf Shuler 	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
188e62bc9e7SShahaf Shuler 		WARN("unable to query number of statistics");
189e62bc9e7SShahaf Shuler 		return -1;
190e62bc9e7SShahaf Shuler 	}
191e62bc9e7SShahaf Shuler 	return drvinfo.n_stats;
192e62bc9e7SShahaf Shuler }
193e62bc9e7SShahaf Shuler 
194e62bc9e7SShahaf Shuler /**
195a4193ae3SShahaf Shuler  * Init the structures to read device counters.
196a4193ae3SShahaf Shuler  *
197a4193ae3SShahaf Shuler  * @param priv
198a4193ae3SShahaf Shuler  *   Pointer to private structure.
199a4193ae3SShahaf Shuler  */
200a4193ae3SShahaf Shuler void
201a4193ae3SShahaf Shuler priv_xstats_init(struct priv *priv)
202a4193ae3SShahaf Shuler {
203a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
204a4193ae3SShahaf Shuler 	unsigned int i;
205a4193ae3SShahaf Shuler 	unsigned int j;
206a4193ae3SShahaf Shuler 	struct ifreq ifr;
207a4193ae3SShahaf Shuler 	struct ethtool_gstrings *strings = NULL;
208a4193ae3SShahaf Shuler 	unsigned int dev_stats_n;
209a4193ae3SShahaf Shuler 	unsigned int str_sz;
210a4193ae3SShahaf Shuler 
211e62bc9e7SShahaf Shuler 	dev_stats_n = priv_ethtool_get_stats_n(priv);
212a4193ae3SShahaf Shuler 	if (dev_stats_n < 1) {
213a4193ae3SShahaf Shuler 		WARN("no extended statistics available");
214a4193ae3SShahaf Shuler 		return;
215a4193ae3SShahaf Shuler 	}
216a4193ae3SShahaf Shuler 	xstats_ctrl->stats_n = dev_stats_n;
217a4193ae3SShahaf Shuler 	/* Allocate memory to grab stat names and values. */
218a4193ae3SShahaf Shuler 	str_sz = dev_stats_n * ETH_GSTRING_LEN;
219a4193ae3SShahaf Shuler 	strings = (struct ethtool_gstrings *)
220a4193ae3SShahaf Shuler 		  rte_malloc("xstats_strings",
221a4193ae3SShahaf Shuler 			     str_sz + sizeof(struct ethtool_gstrings), 0);
222a4193ae3SShahaf Shuler 	if (!strings) {
223a4193ae3SShahaf Shuler 		WARN("unable to allocate memory for xstats");
224a4193ae3SShahaf Shuler 		return;
225a4193ae3SShahaf Shuler 	}
226a4193ae3SShahaf Shuler 	strings->cmd = ETHTOOL_GSTRINGS;
227a4193ae3SShahaf Shuler 	strings->string_set = ETH_SS_STATS;
228a4193ae3SShahaf Shuler 	strings->len = dev_stats_n;
229a4193ae3SShahaf Shuler 	ifr.ifr_data = (caddr_t)strings;
230a4193ae3SShahaf Shuler 	if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
231a4193ae3SShahaf Shuler 		WARN("unable to get statistic names");
232a4193ae3SShahaf Shuler 		goto free;
233a4193ae3SShahaf Shuler 	}
234a4193ae3SShahaf Shuler 	for (j = 0; j != xstats_n; ++j)
235a4193ae3SShahaf Shuler 		xstats_ctrl->dev_table_idx[j] = dev_stats_n;
236a4193ae3SShahaf Shuler 	for (i = 0; i != dev_stats_n; ++i) {
237a4193ae3SShahaf Shuler 		const char *curr_string = (const char *)
238a4193ae3SShahaf Shuler 			&strings->data[i * ETH_GSTRING_LEN];
239a4193ae3SShahaf Shuler 
240a4193ae3SShahaf Shuler 		for (j = 0; j != xstats_n; ++j) {
241a4193ae3SShahaf Shuler 			if (!strcmp(mlx5_counters_init[j].ctr_name,
242a4193ae3SShahaf Shuler 				    curr_string)) {
243a4193ae3SShahaf Shuler 				xstats_ctrl->dev_table_idx[j] = i;
244a4193ae3SShahaf Shuler 				break;
245a4193ae3SShahaf Shuler 			}
246a4193ae3SShahaf Shuler 		}
247a4193ae3SShahaf Shuler 	}
248a4193ae3SShahaf Shuler 	for (j = 0; j != xstats_n; ++j) {
2494b2e6df2SShahaf Shuler 		if (priv_is_ib_cntr(mlx5_counters_init[j].ctr_name))
250859081d3SShahaf Shuler 			continue;
251a4193ae3SShahaf Shuler 		if (xstats_ctrl->dev_table_idx[j] >= dev_stats_n) {
252a4193ae3SShahaf Shuler 			WARN("counter \"%s\" is not recognized",
253a4193ae3SShahaf Shuler 			     mlx5_counters_init[j].dpdk_name);
254a4193ae3SShahaf Shuler 			goto free;
255a4193ae3SShahaf Shuler 		}
256a4193ae3SShahaf Shuler 	}
257a4193ae3SShahaf Shuler 	/* Copy to base at first time. */
258a4193ae3SShahaf Shuler 	assert(xstats_n <= MLX5_MAX_XSTATS);
259a4193ae3SShahaf Shuler 	priv_read_dev_counters(priv, xstats_ctrl->base);
260a4193ae3SShahaf Shuler free:
261a4193ae3SShahaf Shuler 	rte_free(strings);
262a4193ae3SShahaf Shuler }
263a4193ae3SShahaf Shuler 
264a4193ae3SShahaf Shuler /**
265a4193ae3SShahaf Shuler  * Get device extended statistics.
266a4193ae3SShahaf Shuler  *
267a4193ae3SShahaf Shuler  * @param priv
268a4193ae3SShahaf Shuler  *   Pointer to private structure.
269a4193ae3SShahaf Shuler  * @param[out] stats
270a4193ae3SShahaf Shuler  *   Pointer to rte extended stats table.
271a4193ae3SShahaf Shuler  *
272a4193ae3SShahaf Shuler  * @return
273a4193ae3SShahaf Shuler  *   Number of extended stats on success and stats is filled,
274a4193ae3SShahaf Shuler  *   negative on error.
275a4193ae3SShahaf Shuler  */
276a4193ae3SShahaf Shuler static int
277a4193ae3SShahaf Shuler priv_xstats_get(struct priv *priv, struct rte_eth_xstat *stats)
278a4193ae3SShahaf Shuler {
279a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
280a4193ae3SShahaf Shuler 	unsigned int i;
281a4193ae3SShahaf Shuler 	unsigned int n = xstats_n;
282a4193ae3SShahaf Shuler 	uint64_t counters[n];
283a4193ae3SShahaf Shuler 
284a4193ae3SShahaf Shuler 	if (priv_read_dev_counters(priv, counters) < 0)
285a4193ae3SShahaf Shuler 		return -1;
286a4193ae3SShahaf Shuler 	for (i = 0; i != xstats_n; ++i) {
287a4193ae3SShahaf Shuler 		stats[i].id = i;
288a4193ae3SShahaf Shuler 		stats[i].value = (counters[i] - xstats_ctrl->base[i]);
289a4193ae3SShahaf Shuler 	}
290a4193ae3SShahaf Shuler 	return n;
291a4193ae3SShahaf Shuler }
292a4193ae3SShahaf Shuler 
293a4193ae3SShahaf Shuler /**
294a4193ae3SShahaf Shuler  * Reset device extended statistics.
295a4193ae3SShahaf Shuler  *
296a4193ae3SShahaf Shuler  * @param priv
297a4193ae3SShahaf Shuler  *   Pointer to private structure.
298a4193ae3SShahaf Shuler  */
299a4193ae3SShahaf Shuler static void
300a4193ae3SShahaf Shuler priv_xstats_reset(struct priv *priv)
301a4193ae3SShahaf Shuler {
302a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
303a4193ae3SShahaf Shuler 	unsigned int i;
304a4193ae3SShahaf Shuler 	unsigned int n = xstats_n;
305a4193ae3SShahaf Shuler 	uint64_t counters[n];
306a4193ae3SShahaf Shuler 
307a4193ae3SShahaf Shuler 	if (priv_read_dev_counters(priv, counters) < 0)
308a4193ae3SShahaf Shuler 		return;
309a4193ae3SShahaf Shuler 	for (i = 0; i != n; ++i)
310a4193ae3SShahaf Shuler 		xstats_ctrl->base[i] = counters[i];
311a4193ae3SShahaf Shuler }
312a4193ae3SShahaf Shuler 
31387011737SAdrien Mazarguil /**
31487011737SAdrien Mazarguil  * DPDK callback to get device statistics.
31587011737SAdrien Mazarguil  *
31687011737SAdrien Mazarguil  * @param dev
31787011737SAdrien Mazarguil  *   Pointer to Ethernet device structure.
31887011737SAdrien Mazarguil  * @param[out] stats
31987011737SAdrien Mazarguil  *   Stats structure output buffer.
32087011737SAdrien Mazarguil  */
321*d5b0924bSMatan Azrad int
32287011737SAdrien Mazarguil mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
32387011737SAdrien Mazarguil {
324a48deadaSOr Ami 	struct priv *priv = mlx5_get_priv(dev);
32587011737SAdrien Mazarguil 	struct rte_eth_stats tmp = {0};
32687011737SAdrien Mazarguil 	unsigned int i;
32787011737SAdrien Mazarguil 	unsigned int idx;
32887011737SAdrien Mazarguil 
32987011737SAdrien Mazarguil 	priv_lock(priv);
33087011737SAdrien Mazarguil 	/* Add software counters. */
33187011737SAdrien Mazarguil 	for (i = 0; (i != priv->rxqs_n); ++i) {
33278142aacSNélio Laranjeiro 		struct mlx5_rxq_data *rxq = (*priv->rxqs)[i];
33387011737SAdrien Mazarguil 
33487011737SAdrien Mazarguil 		if (rxq == NULL)
33587011737SAdrien Mazarguil 			continue;
33687011737SAdrien Mazarguil 		idx = rxq->stats.idx;
33787011737SAdrien Mazarguil 		if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
33887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
33987011737SAdrien Mazarguil 			tmp.q_ipackets[idx] += rxq->stats.ipackets;
34087011737SAdrien Mazarguil 			tmp.q_ibytes[idx] += rxq->stats.ibytes;
34187011737SAdrien Mazarguil #endif
34287011737SAdrien Mazarguil 			tmp.q_errors[idx] += (rxq->stats.idropped +
34387011737SAdrien Mazarguil 					      rxq->stats.rx_nombuf);
34487011737SAdrien Mazarguil 		}
34587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
34687011737SAdrien Mazarguil 		tmp.ipackets += rxq->stats.ipackets;
34787011737SAdrien Mazarguil 		tmp.ibytes += rxq->stats.ibytes;
34887011737SAdrien Mazarguil #endif
34987011737SAdrien Mazarguil 		tmp.ierrors += rxq->stats.idropped;
35087011737SAdrien Mazarguil 		tmp.rx_nombuf += rxq->stats.rx_nombuf;
35187011737SAdrien Mazarguil 	}
35287011737SAdrien Mazarguil 	for (i = 0; (i != priv->txqs_n); ++i) {
353991b04f6SNélio Laranjeiro 		struct mlx5_txq_data *txq = (*priv->txqs)[i];
35487011737SAdrien Mazarguil 
35587011737SAdrien Mazarguil 		if (txq == NULL)
35687011737SAdrien Mazarguil 			continue;
35787011737SAdrien Mazarguil 		idx = txq->stats.idx;
35887011737SAdrien Mazarguil 		if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
35987011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
36087011737SAdrien Mazarguil 			tmp.q_opackets[idx] += txq->stats.opackets;
36187011737SAdrien Mazarguil 			tmp.q_obytes[idx] += txq->stats.obytes;
36287011737SAdrien Mazarguil #endif
3639f9a48ebSShahaf Shuler 			tmp.q_errors[idx] += txq->stats.oerrors;
36487011737SAdrien Mazarguil 		}
36587011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
36687011737SAdrien Mazarguil 		tmp.opackets += txq->stats.opackets;
36787011737SAdrien Mazarguil 		tmp.obytes += txq->stats.obytes;
36887011737SAdrien Mazarguil #endif
3699f9a48ebSShahaf Shuler 		tmp.oerrors += txq->stats.oerrors;
37087011737SAdrien Mazarguil 	}
37187011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
37287011737SAdrien Mazarguil 	/* FIXME: retrieve and add hardware counters. */
37387011737SAdrien Mazarguil #endif
37487011737SAdrien Mazarguil 	*stats = tmp;
37587011737SAdrien Mazarguil 	priv_unlock(priv);
376*d5b0924bSMatan Azrad 	return 0;
37787011737SAdrien Mazarguil }
37887011737SAdrien Mazarguil 
37987011737SAdrien Mazarguil /**
38087011737SAdrien Mazarguil  * DPDK callback to clear device statistics.
38187011737SAdrien Mazarguil  *
38287011737SAdrien Mazarguil  * @param dev
38387011737SAdrien Mazarguil  *   Pointer to Ethernet device structure.
38487011737SAdrien Mazarguil  */
38587011737SAdrien Mazarguil void
38687011737SAdrien Mazarguil mlx5_stats_reset(struct rte_eth_dev *dev)
38787011737SAdrien Mazarguil {
38887011737SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
38987011737SAdrien Mazarguil 	unsigned int i;
39087011737SAdrien Mazarguil 	unsigned int idx;
39187011737SAdrien Mazarguil 
39287011737SAdrien Mazarguil 	priv_lock(priv);
39387011737SAdrien Mazarguil 	for (i = 0; (i != priv->rxqs_n); ++i) {
39487011737SAdrien Mazarguil 		if ((*priv->rxqs)[i] == NULL)
39587011737SAdrien Mazarguil 			continue;
39687011737SAdrien Mazarguil 		idx = (*priv->rxqs)[i]->stats.idx;
39787011737SAdrien Mazarguil 		(*priv->rxqs)[i]->stats =
39887011737SAdrien Mazarguil 			(struct mlx5_rxq_stats){ .idx = idx };
39987011737SAdrien Mazarguil 	}
40087011737SAdrien Mazarguil 	for (i = 0; (i != priv->txqs_n); ++i) {
40187011737SAdrien Mazarguil 		if ((*priv->txqs)[i] == NULL)
40287011737SAdrien Mazarguil 			continue;
4037efc807dSAdrien Mazarguil 		idx = (*priv->txqs)[i]->stats.idx;
40487011737SAdrien Mazarguil 		(*priv->txqs)[i]->stats =
40587011737SAdrien Mazarguil 			(struct mlx5_txq_stats){ .idx = idx };
40687011737SAdrien Mazarguil 	}
40787011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
40887011737SAdrien Mazarguil 	/* FIXME: reset hardware counters. */
40987011737SAdrien Mazarguil #endif
41087011737SAdrien Mazarguil 	priv_unlock(priv);
41187011737SAdrien Mazarguil }
412a4193ae3SShahaf Shuler 
413a4193ae3SShahaf Shuler /**
414a4193ae3SShahaf Shuler  * DPDK callback to get extended device statistics.
415a4193ae3SShahaf Shuler  *
416a4193ae3SShahaf Shuler  * @param dev
417a4193ae3SShahaf Shuler  *   Pointer to Ethernet device structure.
418a4193ae3SShahaf Shuler  * @param[out] stats
419a4193ae3SShahaf Shuler  *   Stats table output buffer.
420a4193ae3SShahaf Shuler  * @param n
421a4193ae3SShahaf Shuler  *   The size of the stats table.
422a4193ae3SShahaf Shuler  *
423a4193ae3SShahaf Shuler  * @return
424a4193ae3SShahaf Shuler  *   Number of xstats on success, negative on failure.
425a4193ae3SShahaf Shuler  */
426a4193ae3SShahaf Shuler int
427a4193ae3SShahaf Shuler mlx5_xstats_get(struct rte_eth_dev *dev,
428a4193ae3SShahaf Shuler 		struct rte_eth_xstat *stats, unsigned int n)
429a4193ae3SShahaf Shuler {
430a4193ae3SShahaf Shuler 	struct priv *priv = mlx5_get_priv(dev);
431a4193ae3SShahaf Shuler 	int ret = xstats_n;
432a4193ae3SShahaf Shuler 
433a4193ae3SShahaf Shuler 	if (n >= xstats_n && stats) {
434e62bc9e7SShahaf Shuler 		struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
435e62bc9e7SShahaf Shuler 		int stats_n;
436e62bc9e7SShahaf Shuler 
437a4193ae3SShahaf Shuler 		priv_lock(priv);
438e62bc9e7SShahaf Shuler 		stats_n = priv_ethtool_get_stats_n(priv);
439b5743da3SMatan Azrad 		if (stats_n < 0) {
440b5743da3SMatan Azrad 			priv_unlock(priv);
441e62bc9e7SShahaf Shuler 			return -1;
442b5743da3SMatan Azrad 		}
443e62bc9e7SShahaf Shuler 		if (xstats_ctrl->stats_n != stats_n)
444e62bc9e7SShahaf Shuler 			priv_xstats_init(priv);
445a4193ae3SShahaf Shuler 		ret = priv_xstats_get(priv, stats);
446a4193ae3SShahaf Shuler 		priv_unlock(priv);
447a4193ae3SShahaf Shuler 	}
448a4193ae3SShahaf Shuler 	return ret;
449a4193ae3SShahaf Shuler }
450a4193ae3SShahaf Shuler 
451a4193ae3SShahaf Shuler /**
452a4193ae3SShahaf Shuler  * DPDK callback to clear device extended statistics.
453a4193ae3SShahaf Shuler  *
454a4193ae3SShahaf Shuler  * @param dev
455a4193ae3SShahaf Shuler  *   Pointer to Ethernet device structure.
456a4193ae3SShahaf Shuler  */
457a4193ae3SShahaf Shuler void
458a4193ae3SShahaf Shuler mlx5_xstats_reset(struct rte_eth_dev *dev)
459a4193ae3SShahaf Shuler {
460a4193ae3SShahaf Shuler 	struct priv *priv = mlx5_get_priv(dev);
461e62bc9e7SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
462e62bc9e7SShahaf Shuler 	int stats_n;
463a4193ae3SShahaf Shuler 
464a4193ae3SShahaf Shuler 	priv_lock(priv);
465e62bc9e7SShahaf Shuler 	stats_n = priv_ethtool_get_stats_n(priv);
466e62bc9e7SShahaf Shuler 	if (stats_n < 0)
467b5743da3SMatan Azrad 		goto unlock;
468e62bc9e7SShahaf Shuler 	if (xstats_ctrl->stats_n != stats_n)
469e62bc9e7SShahaf Shuler 		priv_xstats_init(priv);
470a4193ae3SShahaf Shuler 	priv_xstats_reset(priv);
471b5743da3SMatan Azrad unlock:
472a4193ae3SShahaf Shuler 	priv_unlock(priv);
473a4193ae3SShahaf Shuler }
474a4193ae3SShahaf Shuler 
475a4193ae3SShahaf Shuler /**
476a4193ae3SShahaf Shuler  * DPDK callback to retrieve names of extended device statistics
477a4193ae3SShahaf Shuler  *
478a4193ae3SShahaf Shuler  * @param dev
479a4193ae3SShahaf Shuler  *   Pointer to Ethernet device structure.
480a4193ae3SShahaf Shuler  * @param[out] xstats_names
481a4193ae3SShahaf Shuler  *   Buffer to insert names into.
482a4193ae3SShahaf Shuler  * @param n
483a4193ae3SShahaf Shuler  *   Number of names.
484a4193ae3SShahaf Shuler  *
485a4193ae3SShahaf Shuler  * @return
486a4193ae3SShahaf Shuler  *   Number of xstats names.
487a4193ae3SShahaf Shuler  */
488a4193ae3SShahaf Shuler int
489a4193ae3SShahaf Shuler mlx5_xstats_get_names(struct rte_eth_dev *dev,
490a4193ae3SShahaf Shuler 		struct rte_eth_xstat_name *xstats_names, unsigned int n)
491a4193ae3SShahaf Shuler {
492a4193ae3SShahaf Shuler 	struct priv *priv = mlx5_get_priv(dev);
493a4193ae3SShahaf Shuler 	unsigned int i;
494a4193ae3SShahaf Shuler 
495a4193ae3SShahaf Shuler 	if (n >= xstats_n && xstats_names) {
496a4193ae3SShahaf Shuler 		priv_lock(priv);
497a4193ae3SShahaf Shuler 		for (i = 0; i != xstats_n; ++i) {
498a4193ae3SShahaf Shuler 			strncpy(xstats_names[i].name,
499a4193ae3SShahaf Shuler 				mlx5_counters_init[i].dpdk_name,
500a4193ae3SShahaf Shuler 				RTE_ETH_XSTATS_NAME_SIZE);
501a4193ae3SShahaf Shuler 			xstats_names[i].name[RTE_ETH_XSTATS_NAME_SIZE - 1] = 0;
502a4193ae3SShahaf Shuler 		}
503a4193ae3SShahaf Shuler 		priv_unlock(priv);
504a4193ae3SShahaf Shuler 	}
505a4193ae3SShahaf Shuler 	return xstats_n;
506a4193ae3SShahaf Shuler }
507