net/mlx5: remove unused interface name query
[dpdk.git] / drivers / net / mlx5 / mlx5_stats.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2015 6WIND S.A.
5  *   Copyright 2015 Mellanox.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <linux/sockios.h>
35 #include <linux/ethtool.h>
36
37 /* DPDK headers don't like -pedantic. */
38 #ifdef PEDANTIC
39 #pragma GCC diagnostic ignored "-Wpedantic"
40 #endif
41 #include <rte_ethdev.h>
42 #include <rte_common.h>
43 #include <rte_malloc.h>
44 #ifdef PEDANTIC
45 #pragma GCC diagnostic error "-Wpedantic"
46 #endif
47
48 #include "mlx5.h"
49 #include "mlx5_rxtx.h"
50 #include "mlx5_defs.h"
51
52 struct mlx5_counter_ctrl {
53         /* Name of the counter. */
54         char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
55         /* Name of the counter on the device table. */
56         char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
57 };
58
59 static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
60         {
61                 .dpdk_name = "rx_port_unicast_bytes",
62                 .ctr_name = "rx_vport_unicast_bytes",
63         },
64         {
65                 .dpdk_name = "rx_port_multicast_bytes",
66                 .ctr_name = "rx_vport_multicast_bytes",
67         },
68         {
69                 .dpdk_name = "rx_port_broadcast_bytes",
70                 .ctr_name = "rx_vport_broadcast_bytes",
71         },
72         {
73                 .dpdk_name = "rx_port_unicast_packets",
74                 .ctr_name = "rx_vport_unicast_packets",
75         },
76         {
77                 .dpdk_name = "rx_port_multicast_packets",
78                 .ctr_name = "rx_vport_multicast_packets",
79         },
80         {
81                 .dpdk_name = "rx_port_broadcast_packets",
82                 .ctr_name = "rx_vport_broadcast_packets",
83         },
84         {
85                 .dpdk_name = "tx_port_unicast_bytes",
86                 .ctr_name = "tx_vport_unicast_bytes",
87         },
88         {
89                 .dpdk_name = "tx_port_multicast_bytes",
90                 .ctr_name = "tx_vport_multicast_bytes",
91         },
92         {
93                 .dpdk_name = "tx_port_broadcast_bytes",
94                 .ctr_name = "tx_vport_broadcast_bytes",
95         },
96         {
97                 .dpdk_name = "tx_port_unicast_packets",
98                 .ctr_name = "tx_vport_unicast_packets",
99         },
100         {
101                 .dpdk_name = "tx_port_multicast_packets",
102                 .ctr_name = "tx_vport_multicast_packets",
103         },
104         {
105                 .dpdk_name = "tx_port_broadcast_packets",
106                 .ctr_name = "tx_vport_broadcast_packets",
107         },
108         {
109                 .dpdk_name = "rx_wqe_err",
110                 .ctr_name = "rx_wqe_err",
111         },
112         {
113                 .dpdk_name = "rx_crc_errors_phy",
114                 .ctr_name = "rx_crc_errors_phy",
115         },
116         {
117                 .dpdk_name = "rx_in_range_len_errors_phy",
118                 .ctr_name = "rx_in_range_len_errors_phy",
119         },
120         {
121                 .dpdk_name = "rx_symbol_err_phy",
122                 .ctr_name = "rx_symbol_err_phy",
123         },
124         {
125                 .dpdk_name = "tx_errors_phy",
126                 .ctr_name = "tx_errors_phy",
127         },
128         {
129                 .dpdk_name = "rx_out_of_buffer",
130                 .ctr_name = "out_of_buffer",
131         },
132 };
133
134 static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
135
136 /**
137  * Read device counters table.
138  *
139  * @param priv
140  *   Pointer to private structure.
141  * @param[out] stats
142  *   Counters table output buffer.
143  *
144  * @return
145  *   0 on success and stats is filled, negative on error.
146  */
147 static int
148 priv_read_dev_counters(struct priv *priv, uint64_t *stats)
149 {
150         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
151         unsigned int i;
152         struct ifreq ifr;
153         unsigned int stats_sz = (xstats_ctrl->stats_n * sizeof(uint64_t)) +
154                                  sizeof(struct ethtool_stats);
155         struct ethtool_stats et_stats[(stats_sz + (
156                                       sizeof(struct ethtool_stats) - 1)) /
157                                       sizeof(struct ethtool_stats)];
158
159         et_stats->cmd = ETHTOOL_GSTATS;
160         et_stats->n_stats = xstats_ctrl->stats_n;
161         ifr.ifr_data = (caddr_t)et_stats;
162         if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
163                 WARN("unable to read statistic values from device");
164                 return -1;
165         }
166         for (i = 0; i != xstats_n; ++i) {
167                 if (priv_is_ib_cntr(mlx5_counters_init[i].ctr_name))
168                         priv_get_cntr_sysfs(priv,
169                                             mlx5_counters_init[i].ctr_name,
170                                             &stats[i]);
171                 else
172                         stats[i] = (uint64_t)
173                                 et_stats->data[xstats_ctrl->dev_table_idx[i]];
174         }
175         return 0;
176 }
177
178 /**
179  * Init the structures to read device counters.
180  *
181  * @param priv
182  *   Pointer to private structure.
183  */
184 void
185 priv_xstats_init(struct priv *priv)
186 {
187         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
188         unsigned int i;
189         unsigned int j;
190         struct ifreq ifr;
191         struct ethtool_drvinfo drvinfo;
192         struct ethtool_gstrings *strings = NULL;
193         unsigned int dev_stats_n;
194         unsigned int str_sz;
195
196         /* How many statistics are available. */
197         drvinfo.cmd = ETHTOOL_GDRVINFO;
198         ifr.ifr_data = (caddr_t)&drvinfo;
199         if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
200                 WARN("unable to get driver info");
201                 return;
202         }
203         dev_stats_n = drvinfo.n_stats;
204         if (dev_stats_n < 1) {
205                 WARN("no extended statistics available");
206                 return;
207         }
208         xstats_ctrl->stats_n = dev_stats_n;
209         /* Allocate memory to grab stat names and values. */
210         str_sz = dev_stats_n * ETH_GSTRING_LEN;
211         strings = (struct ethtool_gstrings *)
212                   rte_malloc("xstats_strings",
213                              str_sz + sizeof(struct ethtool_gstrings), 0);
214         if (!strings) {
215                 WARN("unable to allocate memory for xstats");
216                 return;
217         }
218         strings->cmd = ETHTOOL_GSTRINGS;
219         strings->string_set = ETH_SS_STATS;
220         strings->len = dev_stats_n;
221         ifr.ifr_data = (caddr_t)strings;
222         if (priv_ifreq(priv, SIOCETHTOOL, &ifr) != 0) {
223                 WARN("unable to get statistic names");
224                 goto free;
225         }
226         for (j = 0; j != xstats_n; ++j)
227                 xstats_ctrl->dev_table_idx[j] = dev_stats_n;
228         for (i = 0; i != dev_stats_n; ++i) {
229                 const char *curr_string = (const char *)
230                         &strings->data[i * ETH_GSTRING_LEN];
231
232                 for (j = 0; j != xstats_n; ++j) {
233                         if (!strcmp(mlx5_counters_init[j].ctr_name,
234                                     curr_string)) {
235                                 xstats_ctrl->dev_table_idx[j] = i;
236                                 break;
237                         }
238                 }
239         }
240         for (j = 0; j != xstats_n; ++j) {
241                 if (priv_is_ib_cntr(mlx5_counters_init[i].ctr_name))
242                         continue;
243                 if (xstats_ctrl->dev_table_idx[j] >= dev_stats_n) {
244                         WARN("counter \"%s\" is not recognized",
245                              mlx5_counters_init[j].dpdk_name);
246                         goto free;
247                 }
248         }
249         /* Copy to base at first time. */
250         assert(xstats_n <= MLX5_MAX_XSTATS);
251         priv_read_dev_counters(priv, xstats_ctrl->base);
252 free:
253         rte_free(strings);
254 }
255
256 /**
257  * Get device extended statistics.
258  *
259  * @param priv
260  *   Pointer to private structure.
261  * @param[out] stats
262  *   Pointer to rte extended stats table.
263  *
264  * @return
265  *   Number of extended stats on success and stats is filled,
266  *   negative on error.
267  */
268 static int
269 priv_xstats_get(struct priv *priv, struct rte_eth_xstat *stats)
270 {
271         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
272         unsigned int i;
273         unsigned int n = xstats_n;
274         uint64_t counters[n];
275
276         if (priv_read_dev_counters(priv, counters) < 0)
277                 return -1;
278         for (i = 0; i != xstats_n; ++i) {
279                 stats[i].id = i;
280                 stats[i].value = (counters[i] - xstats_ctrl->base[i]);
281         }
282         return n;
283 }
284
285 /**
286  * Reset device extended statistics.
287  *
288  * @param priv
289  *   Pointer to private structure.
290  */
291 static void
292 priv_xstats_reset(struct priv *priv)
293 {
294         struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
295         unsigned int i;
296         unsigned int n = xstats_n;
297         uint64_t counters[n];
298
299         if (priv_read_dev_counters(priv, counters) < 0)
300                 return;
301         for (i = 0; i != n; ++i)
302                 xstats_ctrl->base[i] = counters[i];
303 }
304
305 /**
306  * DPDK callback to get device statistics.
307  *
308  * @param dev
309  *   Pointer to Ethernet device structure.
310  * @param[out] stats
311  *   Stats structure output buffer.
312  */
313 void
314 mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
315 {
316         struct priv *priv = mlx5_get_priv(dev);
317         struct rte_eth_stats tmp = {0};
318         unsigned int i;
319         unsigned int idx;
320
321         priv_lock(priv);
322         /* Add software counters. */
323         for (i = 0; (i != priv->rxqs_n); ++i) {
324                 struct rxq *rxq = (*priv->rxqs)[i];
325
326                 if (rxq == NULL)
327                         continue;
328                 idx = rxq->stats.idx;
329                 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
330 #ifdef MLX5_PMD_SOFT_COUNTERS
331                         tmp.q_ipackets[idx] += rxq->stats.ipackets;
332                         tmp.q_ibytes[idx] += rxq->stats.ibytes;
333 #endif
334                         tmp.q_errors[idx] += (rxq->stats.idropped +
335                                               rxq->stats.rx_nombuf);
336                 }
337 #ifdef MLX5_PMD_SOFT_COUNTERS
338                 tmp.ipackets += rxq->stats.ipackets;
339                 tmp.ibytes += rxq->stats.ibytes;
340 #endif
341                 tmp.ierrors += rxq->stats.idropped;
342                 tmp.rx_nombuf += rxq->stats.rx_nombuf;
343         }
344         for (i = 0; (i != priv->txqs_n); ++i) {
345                 struct txq *txq = (*priv->txqs)[i];
346
347                 if (txq == NULL)
348                         continue;
349                 idx = txq->stats.idx;
350                 if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
351 #ifdef MLX5_PMD_SOFT_COUNTERS
352                         tmp.q_opackets[idx] += txq->stats.opackets;
353                         tmp.q_obytes[idx] += txq->stats.obytes;
354 #endif
355                         tmp.q_errors[idx] += txq->stats.odropped;
356                 }
357 #ifdef MLX5_PMD_SOFT_COUNTERS
358                 tmp.opackets += txq->stats.opackets;
359                 tmp.obytes += txq->stats.obytes;
360 #endif
361                 tmp.oerrors += txq->stats.odropped;
362         }
363 #ifndef MLX5_PMD_SOFT_COUNTERS
364         /* FIXME: retrieve and add hardware counters. */
365 #endif
366         *stats = tmp;
367         priv_unlock(priv);
368 }
369
370 /**
371  * DPDK callback to clear device statistics.
372  *
373  * @param dev
374  *   Pointer to Ethernet device structure.
375  */
376 void
377 mlx5_stats_reset(struct rte_eth_dev *dev)
378 {
379         struct priv *priv = dev->data->dev_private;
380         unsigned int i;
381         unsigned int idx;
382
383         priv_lock(priv);
384         for (i = 0; (i != priv->rxqs_n); ++i) {
385                 if ((*priv->rxqs)[i] == NULL)
386                         continue;
387                 idx = (*priv->rxqs)[i]->stats.idx;
388                 (*priv->rxqs)[i]->stats =
389                         (struct mlx5_rxq_stats){ .idx = idx };
390         }
391         for (i = 0; (i != priv->txqs_n); ++i) {
392                 if ((*priv->txqs)[i] == NULL)
393                         continue;
394                 idx = (*priv->txqs)[i]->stats.idx;
395                 (*priv->txqs)[i]->stats =
396                         (struct mlx5_txq_stats){ .idx = idx };
397         }
398 #ifndef MLX5_PMD_SOFT_COUNTERS
399         /* FIXME: reset hardware counters. */
400 #endif
401         priv_unlock(priv);
402 }
403
404 /**
405  * DPDK callback to get extended device statistics.
406  *
407  * @param dev
408  *   Pointer to Ethernet device structure.
409  * @param[out] stats
410  *   Stats table output buffer.
411  * @param n
412  *   The size of the stats table.
413  *
414  * @return
415  *   Number of xstats on success, negative on failure.
416  */
417 int
418 mlx5_xstats_get(struct rte_eth_dev *dev,
419                 struct rte_eth_xstat *stats, unsigned int n)
420 {
421         struct priv *priv = mlx5_get_priv(dev);
422         int ret = xstats_n;
423
424         if (n >= xstats_n && stats) {
425                 priv_lock(priv);
426                 ret = priv_xstats_get(priv, stats);
427                 priv_unlock(priv);
428         }
429         return ret;
430 }
431
432 /**
433  * DPDK callback to clear device extended statistics.
434  *
435  * @param dev
436  *   Pointer to Ethernet device structure.
437  */
438 void
439 mlx5_xstats_reset(struct rte_eth_dev *dev)
440 {
441         struct priv *priv = mlx5_get_priv(dev);
442
443         priv_lock(priv);
444         priv_xstats_reset(priv);
445         priv_unlock(priv);
446 }
447
448 /**
449  * DPDK callback to retrieve names of extended device statistics
450  *
451  * @param dev
452  *   Pointer to Ethernet device structure.
453  * @param[out] xstats_names
454  *   Buffer to insert names into.
455  * @param n
456  *   Number of names.
457  *
458  * @return
459  *   Number of xstats names.
460  */
461 int
462 mlx5_xstats_get_names(struct rte_eth_dev *dev,
463                 struct rte_eth_xstat_name *xstats_names, unsigned int n)
464 {
465         struct priv *priv = mlx5_get_priv(dev);
466         unsigned int i;
467
468         if (n >= xstats_n && xstats_names) {
469                 priv_lock(priv);
470                 for (i = 0; i != xstats_n; ++i) {
471                         strncpy(xstats_names[i].name,
472                                 mlx5_counters_init[i].dpdk_name,
473                                 RTE_ETH_XSTATS_NAME_SIZE);
474                         xstats_names[i].name[RTE_ETH_XSTATS_NAME_SIZE - 1] = 0;
475                 }
476                 priv_unlock(priv);
477         }
478         return xstats_n;
479 }