net/ice/base: support priority configuration of exact node
[dpdk.git] / drivers / net / mlx5 / mlx5_stats.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2015 6WIND S.A.
3  * Copyright 2015 Mellanox Technologies, Ltd
4  */
5
6 #include <inttypes.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <unistd.h>
10
11 #include <ethdev_driver.h>
12 #include <rte_common.h>
13 #include <rte_malloc.h>
14
15 #include <mlx5_common.h>
16
17 #include "mlx5_defs.h"
18 #include "mlx5.h"
19 #include "mlx5_rx.h"
20 #include "mlx5_tx.h"
21 #include "mlx5_malloc.h"
22
23 /**
24  * DPDK callback to get extended device statistics.
25  *
26  * @param dev
27  *   Pointer to Ethernet device.
28  * @param[out] stats
29  *   Pointer to rte extended stats table.
30  * @param n
31  *   The size of the stats table.
32  *
33  * @return
34  *   Number of extended stats on success and stats is filled,
35  *   negative on error and rte_errno is set.
36  */
37 int
38 mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
39                 unsigned int n)
40 {
41         struct mlx5_priv *priv = dev->data->dev_private;
42         unsigned int i;
43         uint64_t counters[n];
44         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
45         uint16_t mlx5_stats_n = xstats_ctrl->mlx5_stats_n;
46
47         if (n >= mlx5_stats_n && stats) {
48                 int stats_n;
49                 int ret;
50
51                 stats_n = mlx5_os_get_stats_n(dev);
52                 if (stats_n < 0)
53                         return stats_n;
54                 if (xstats_ctrl->stats_n != stats_n)
55                         mlx5_os_stats_init(dev);
56                 ret = mlx5_os_read_dev_counters(dev, counters);
57                 if (ret)
58                         return ret;
59                 for (i = 0; i != mlx5_stats_n; ++i) {
60                         stats[i].id = i;
61                         if (xstats_ctrl->info[i].dev) {
62                                 uint64_t wrap_n;
63                                 uint64_t hw_stat = xstats_ctrl->hw_stats[i];
64
65                                 stats[i].value = (counters[i] -
66                                                   xstats_ctrl->base[i]) &
67                                                   (uint64_t)UINT32_MAX;
68                                 wrap_n = hw_stat >> 32;
69                                 if (stats[i].value <
70                                             (hw_stat & (uint64_t)UINT32_MAX))
71                                         wrap_n++;
72                                 stats[i].value |= (wrap_n) << 32;
73                                 xstats_ctrl->hw_stats[i] = stats[i].value;
74                         } else {
75                                 stats[i].value =
76                                         (counters[i] - xstats_ctrl->base[i]);
77                         }
78                 }
79         }
80         mlx5_stats_n = mlx5_txpp_xstats_get(dev, stats, n, mlx5_stats_n);
81         return mlx5_stats_n;
82 }
83
84 /**
85  * DPDK callback to get device statistics.
86  *
87  * @param dev
88  *   Pointer to Ethernet device structure.
89  * @param[out] stats
90  *   Stats structure output buffer.
91  *
92  * @return
93  *   0 on success and stats is filled, negative errno value otherwise and
94  *   rte_errno is set.
95  */
96 int
97 mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
98 {
99         struct mlx5_priv *priv = dev->data->dev_private;
100         struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
101         struct rte_eth_stats tmp;
102         unsigned int i;
103         unsigned int idx;
104         uint64_t wrap_n;
105         int ret;
106
107         memset(&tmp, 0, sizeof(tmp));
108         /* Add software counters. */
109         for (i = 0; (i != priv->rxqs_n); ++i) {
110                 struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, i);
111
112                 if (rxq == NULL)
113                         continue;
114                 idx = rxq->idx;
115                 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
116 #ifdef MLX5_PMD_SOFT_COUNTERS
117                         tmp.q_ipackets[idx] += rxq->stats.ipackets -
118                                 rxq->stats_reset.ipackets;
119                         tmp.q_ibytes[idx] += rxq->stats.ibytes -
120                                 rxq->stats_reset.ibytes;
121 #endif
122                         tmp.q_errors[idx] += (rxq->stats.idropped +
123                                               rxq->stats.rx_nombuf) -
124                                               (rxq->stats_reset.idropped +
125                                               rxq->stats_reset.rx_nombuf);
126                 }
127 #ifdef MLX5_PMD_SOFT_COUNTERS
128                 tmp.ipackets += rxq->stats.ipackets - rxq->stats_reset.ipackets;
129                 tmp.ibytes += rxq->stats.ibytes - rxq->stats_reset.ibytes;
130 #endif
131                 tmp.ierrors += rxq->stats.idropped - rxq->stats_reset.idropped;
132                 tmp.rx_nombuf += rxq->stats.rx_nombuf -
133                                         rxq->stats_reset.rx_nombuf;
134         }
135         for (i = 0; (i != priv->txqs_n); ++i) {
136                 struct mlx5_txq_data *txq = (*priv->txqs)[i];
137
138                 if (txq == NULL)
139                         continue;
140                 idx = txq->idx;
141                 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
142 #ifdef MLX5_PMD_SOFT_COUNTERS
143                         tmp.q_opackets[idx] += txq->stats.opackets -
144                                                 txq->stats_reset.opackets;
145                         tmp.q_obytes[idx] += txq->stats.obytes -
146                                                 txq->stats_reset.obytes;
147 #endif
148                 }
149 #ifdef MLX5_PMD_SOFT_COUNTERS
150                 tmp.opackets += txq->stats.opackets - txq->stats_reset.opackets;
151                 tmp.obytes += txq->stats.obytes - txq->stats_reset.obytes;
152 #endif
153                 tmp.oerrors += txq->stats.oerrors - txq->stats_reset.oerrors;
154         }
155         ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &tmp.imissed);
156         if (ret == 0) {
157                 tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) &
158                                  (uint64_t)UINT32_MAX;
159                 wrap_n = stats_ctrl->imissed >> 32;
160                 if (tmp.imissed < (stats_ctrl->imissed & (uint64_t)UINT32_MAX))
161                         wrap_n++;
162                 tmp.imissed |= (wrap_n) << 32;
163                 stats_ctrl->imissed = tmp.imissed;
164         } else {
165                 tmp.imissed = stats_ctrl->imissed;
166         }
167 #ifndef MLX5_PMD_SOFT_COUNTERS
168         /* FIXME: retrieve and add hardware counters. */
169 #endif
170         *stats = tmp;
171         return 0;
172 }
173
174 /**
175  * DPDK callback to clear device statistics.
176  *
177  * @param dev
178  *   Pointer to Ethernet device structure.
179  *
180  * @return
181  *   always 0 on success and stats is reset
182  */
183 int
184 mlx5_stats_reset(struct rte_eth_dev *dev)
185 {
186         struct mlx5_priv *priv = dev->data->dev_private;
187         struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
188         unsigned int i;
189
190         for (i = 0; (i != priv->rxqs_n); ++i) {
191                 struct mlx5_rxq_data *rxq_data = mlx5_rxq_data_get(dev, i);
192
193                 if (rxq_data == NULL)
194                         continue;
195                 rxq_data->stats_reset = rxq_data->stats;
196         }
197         for (i = 0; (i != priv->txqs_n); ++i) {
198                 struct mlx5_txq_data *txq_data = (*priv->txqs)[i];
199
200                 if (txq_data == NULL)
201                         continue;
202                 txq_data->stats_reset = txq_data->stats;
203         }
204         mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
205         stats_ctrl->imissed = 0;
206 #ifndef MLX5_PMD_SOFT_COUNTERS
207         /* FIXME: reset hardware counters. */
208 #endif
209
210         return 0;
211 }
212
213 /**
214  * DPDK callback to clear device extended statistics.
215  *
216  * @param dev
217  *   Pointer to Ethernet device structure.
218  *
219  * @return
220  *   0 on success and stats is reset, negative errno value otherwise and
221  *   rte_errno is set.
222  */
223 int
224 mlx5_xstats_reset(struct rte_eth_dev *dev)
225 {
226         struct mlx5_priv *priv = dev->data->dev_private;
227         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
228         int stats_n;
229         unsigned int i;
230         uint64_t *counters;
231         int ret;
232
233         stats_n = mlx5_os_get_stats_n(dev);
234         if (stats_n < 0) {
235                 DRV_LOG(ERR, "port %u cannot get stats: %s", dev->data->port_id,
236                         strerror(-stats_n));
237                 return stats_n;
238         }
239         if (xstats_ctrl->stats_n != stats_n)
240                 mlx5_os_stats_init(dev);
241         counters =  mlx5_malloc(MLX5_MEM_SYS, sizeof(*counters) *
242                         xstats_ctrl->mlx5_stats_n, 0,
243                         SOCKET_ID_ANY);
244         if (!counters) {
245                 DRV_LOG(WARNING, "port %u unable to allocate memory for xstats "
246                                 "counters",
247                      dev->data->port_id);
248                 rte_errno = ENOMEM;
249                 return -rte_errno;
250         }
251         ret = mlx5_os_read_dev_counters(dev, counters);
252         if (ret) {
253                 DRV_LOG(ERR, "port %u cannot read device counters: %s",
254                         dev->data->port_id, strerror(rte_errno));
255                 mlx5_free(counters);
256                 return ret;
257         }
258         for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
259                 xstats_ctrl->base[i] = counters[i];
260                 xstats_ctrl->hw_stats[i] = 0;
261         }
262         mlx5_txpp_xstats_reset(dev);
263         mlx5_free(counters);
264         return 0;
265 }
266
267 /**
268  * DPDK callback to retrieve names of extended device statistics
269  *
270  * @param dev
271  *   Pointer to Ethernet device structure.
272  * @param[out] xstats_names
273  *   Buffer to insert names into.
274  * @param n
275  *   Number of names.
276  *
277  * @return
278  *   Number of xstats names.
279  */
280 int
281 mlx5_xstats_get_names(struct rte_eth_dev *dev,
282                       struct rte_eth_xstat_name *xstats_names, unsigned int n)
283 {
284         unsigned int i;
285         struct mlx5_priv *priv = dev->data->dev_private;
286         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
287         unsigned int mlx5_xstats_n = xstats_ctrl->mlx5_stats_n;
288
289         if (n >= mlx5_xstats_n && xstats_names) {
290                 for (i = 0; i != mlx5_xstats_n; ++i) {
291                         strncpy(xstats_names[i].name,
292                                 xstats_ctrl->info[i].dpdk_name,
293                                 RTE_ETH_XSTATS_NAME_SIZE);
294                         xstats_names[i].name[RTE_ETH_XSTATS_NAME_SIZE - 1] = 0;
295                 }
296         }
297         mlx5_xstats_n = mlx5_txpp_xstats_get_names(dev, xstats_names,
298                                                    n, mlx5_xstats_n);
299         return mlx5_xstats_n;
300 }