18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
287011737SAdrien Mazarguil * Copyright 2015 6WIND S.A.
35feecc57SShahaf Shuler * Copyright 2015 Mellanox Technologies, Ltd
487011737SAdrien Mazarguil */
587011737SAdrien Mazarguil
6fc40db99SAdrien Mazarguil #include <inttypes.h>
7fc40db99SAdrien Mazarguil #include <stdint.h>
8fc40db99SAdrien Mazarguil #include <stdio.h>
900437823SMohsin Shaikh #include <unistd.h>
10a4193ae3SShahaf Shuler
11df96fd0dSBruce Richardson #include <ethdev_driver.h>
12a4193ae3SShahaf Shuler #include <rte_common.h>
13a4193ae3SShahaf Shuler #include <rte_malloc.h>
1487011737SAdrien Mazarguil
1593e30982SMatan Azrad #include <mlx5_common.h>
1693e30982SMatan Azrad
177b4f1e6bSMatan Azrad #include "mlx5_defs.h"
1887011737SAdrien Mazarguil #include "mlx5.h"
19151cbe3aSMichael Baum #include "mlx5_rx.h"
20377b69fbSMichael Baum #include "mlx5_tx.h"
2142dcd453SShiri Kuzin #include "mlx5_malloc.h"
2287011737SAdrien Mazarguil
23a4193ae3SShahaf Shuler /**
24af4f09f2SNélio Laranjeiro * DPDK callback to get extended device statistics.
25a4193ae3SShahaf Shuler *
26af4f09f2SNélio Laranjeiro * @param dev
27af4f09f2SNélio Laranjeiro * Pointer to Ethernet device.
28a4193ae3SShahaf Shuler * @param[out] stats
29a4193ae3SShahaf Shuler * Pointer to rte extended stats table.
30af4f09f2SNélio Laranjeiro * @param n
31af4f09f2SNélio Laranjeiro * The size of the stats table.
32a4193ae3SShahaf Shuler *
33a4193ae3SShahaf Shuler * @return
34a4193ae3SShahaf Shuler * Number of extended stats on success and stats is filled,
35a6d83b6aSNélio Laranjeiro * negative on error and rte_errno is set.
36a4193ae3SShahaf Shuler */
37af4f09f2SNélio Laranjeiro int
mlx5_xstats_get(struct rte_eth_dev * dev,struct rte_eth_xstat * stats,unsigned int n)38af4f09f2SNélio Laranjeiro mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
39af4f09f2SNélio Laranjeiro unsigned int n)
40a4193ae3SShahaf Shuler {
41dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
42*a687c3e6SBing Zhao uint64_t counters[MLX5_MAX_XSTATS];
43af4f09f2SNélio Laranjeiro struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
44*a687c3e6SBing Zhao unsigned int i;
45*a687c3e6SBing Zhao uint16_t stats_n = 0;
46*a687c3e6SBing Zhao uint16_t stats_n_2nd = 0;
471a611fdaSShahaf Shuler uint16_t mlx5_stats_n = xstats_ctrl->mlx5_stats_n;
48*a687c3e6SBing Zhao bool bond_master = (priv->master && priv->pf_bond >= 0);
491a611fdaSShahaf Shuler
501a611fdaSShahaf Shuler if (n >= mlx5_stats_n && stats) {
51a6d83b6aSNélio Laranjeiro int ret;
52af4f09f2SNélio Laranjeiro
53*a687c3e6SBing Zhao ret = mlx5_os_get_stats_n(dev, bond_master, &stats_n, &stats_n_2nd);
54*a687c3e6SBing Zhao if (ret < 0)
55af4f09f2SNélio Laranjeiro return ret;
56*a687c3e6SBing Zhao /*
57*a687c3e6SBing Zhao * The number of statistics fetched via "ETH_SS_STATS" may vary because
58*a687c3e6SBing Zhao * of the port configuration each time. This is also true between 2
59*a687c3e6SBing Zhao * ports. There might be a case that the numbers are the same even if
60*a687c3e6SBing Zhao * configurations are different.
61*a687c3e6SBing Zhao * It is not recommended to change the configuration without using
62*a687c3e6SBing Zhao * RTE API. The port(traffic) restart may trigger another initialization
63*a687c3e6SBing Zhao * to make sure the map are correct.
64*a687c3e6SBing Zhao */
65*a687c3e6SBing Zhao if (xstats_ctrl->stats_n != stats_n ||
66*a687c3e6SBing Zhao (bond_master && xstats_ctrl->stats_n_2nd != stats_n_2nd))
67*a687c3e6SBing Zhao mlx5_os_stats_init(dev);
68*a687c3e6SBing Zhao ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
69*a687c3e6SBing Zhao if (ret < 0)
70*a687c3e6SBing Zhao return ret;
71*a687c3e6SBing Zhao for (i = 0; i != mlx5_stats_n; i++) {
72a4193ae3SShahaf Shuler stats[i].id = i;
7373bf9235SOphir Munk if (xstats_ctrl->info[i].dev) {
74c5193a0bSJiawei Wang uint64_t wrap_n;
75c5193a0bSJiawei Wang uint64_t hw_stat = xstats_ctrl->hw_stats[i];
76c5193a0bSJiawei Wang
77c5193a0bSJiawei Wang stats[i].value = (counters[i] -
78c5193a0bSJiawei Wang xstats_ctrl->base[i]) &
79c5193a0bSJiawei Wang (uint64_t)UINT32_MAX;
80c5193a0bSJiawei Wang wrap_n = hw_stat >> 32;
81c5193a0bSJiawei Wang if (stats[i].value <
82c5193a0bSJiawei Wang (hw_stat & (uint64_t)UINT32_MAX))
83c5193a0bSJiawei Wang wrap_n++;
84c5193a0bSJiawei Wang stats[i].value |= (wrap_n) << 32;
85c5193a0bSJiawei Wang xstats_ctrl->hw_stats[i] = stats[i].value;
86c5193a0bSJiawei Wang } else {
87c5193a0bSJiawei Wang stats[i].value =
88c5193a0bSJiawei Wang (counters[i] - xstats_ctrl->base[i]);
89c5193a0bSJiawei Wang }
90a4193ae3SShahaf Shuler }
91a4193ae3SShahaf Shuler }
923b025c0cSViacheslav Ovsiienko mlx5_stats_n = mlx5_txpp_xstats_get(dev, stats, n, mlx5_stats_n);
931a611fdaSShahaf Shuler return mlx5_stats_n;
94a4193ae3SShahaf Shuler }
95a4193ae3SShahaf Shuler
9687011737SAdrien Mazarguil /**
9787011737SAdrien Mazarguil * DPDK callback to get device statistics.
9887011737SAdrien Mazarguil *
9987011737SAdrien Mazarguil * @param dev
10087011737SAdrien Mazarguil * Pointer to Ethernet device structure.
10187011737SAdrien Mazarguil * @param[out] stats
10287011737SAdrien Mazarguil * Stats structure output buffer.
103a6d83b6aSNélio Laranjeiro *
104a6d83b6aSNélio Laranjeiro * @return
105a6d83b6aSNélio Laranjeiro * 0 on success and stats is filled, negative errno value otherwise and
106a6d83b6aSNélio Laranjeiro * rte_errno is set.
10787011737SAdrien Mazarguil */
108d5b0924bSMatan Azrad int
mlx5_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)10987011737SAdrien Mazarguil mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
11087011737SAdrien Mazarguil {
111dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
112c5193a0bSJiawei Wang struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
1130c15f3c0SAli Alnubani struct rte_eth_stats tmp;
11487011737SAdrien Mazarguil unsigned int i;
11587011737SAdrien Mazarguil unsigned int idx;
116c5193a0bSJiawei Wang uint64_t wrap_n;
117c5193a0bSJiawei Wang int ret;
11887011737SAdrien Mazarguil
1190c15f3c0SAli Alnubani memset(&tmp, 0, sizeof(tmp));
12087011737SAdrien Mazarguil /* Add software counters. */
12187011737SAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) {
1225cf0707fSXueming Li struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, i);
12387011737SAdrien Mazarguil
12487011737SAdrien Mazarguil if (rxq == NULL)
12587011737SAdrien Mazarguil continue;
126d5c900d1SYongseok Koh idx = rxq->idx;
12787011737SAdrien Mazarguil if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
12887011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
129773a7de2SRaja Zidane tmp.q_ipackets[idx] += rxq->stats.ipackets -
130773a7de2SRaja Zidane rxq->stats_reset.ipackets;
131773a7de2SRaja Zidane tmp.q_ibytes[idx] += rxq->stats.ibytes -
132773a7de2SRaja Zidane rxq->stats_reset.ibytes;
13387011737SAdrien Mazarguil #endif
13487011737SAdrien Mazarguil tmp.q_errors[idx] += (rxq->stats.idropped +
135773a7de2SRaja Zidane rxq->stats.rx_nombuf) -
136773a7de2SRaja Zidane (rxq->stats_reset.idropped +
137773a7de2SRaja Zidane rxq->stats_reset.rx_nombuf);
13887011737SAdrien Mazarguil }
13987011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
140773a7de2SRaja Zidane tmp.ipackets += rxq->stats.ipackets - rxq->stats_reset.ipackets;
141773a7de2SRaja Zidane tmp.ibytes += rxq->stats.ibytes - rxq->stats_reset.ibytes;
14287011737SAdrien Mazarguil #endif
143773a7de2SRaja Zidane tmp.ierrors += rxq->stats.idropped - rxq->stats_reset.idropped;
144773a7de2SRaja Zidane tmp.rx_nombuf += rxq->stats.rx_nombuf -
145773a7de2SRaja Zidane rxq->stats_reset.rx_nombuf;
14687011737SAdrien Mazarguil }
14787011737SAdrien Mazarguil for (i = 0; (i != priv->txqs_n); ++i) {
148991b04f6SNélio Laranjeiro struct mlx5_txq_data *txq = (*priv->txqs)[i];
14987011737SAdrien Mazarguil
15087011737SAdrien Mazarguil if (txq == NULL)
15187011737SAdrien Mazarguil continue;
152d5c900d1SYongseok Koh idx = txq->idx;
15387011737SAdrien Mazarguil if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
15487011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
155773a7de2SRaja Zidane tmp.q_opackets[idx] += txq->stats.opackets -
156773a7de2SRaja Zidane txq->stats_reset.opackets;
157773a7de2SRaja Zidane tmp.q_obytes[idx] += txq->stats.obytes -
158773a7de2SRaja Zidane txq->stats_reset.obytes;
15987011737SAdrien Mazarguil #endif
16087011737SAdrien Mazarguil }
16187011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
162773a7de2SRaja Zidane tmp.opackets += txq->stats.opackets - txq->stats_reset.opackets;
163773a7de2SRaja Zidane tmp.obytes += txq->stats.obytes - txq->stats_reset.obytes;
16487011737SAdrien Mazarguil #endif
165773a7de2SRaja Zidane tmp.oerrors += txq->stats.oerrors - txq->stats_reset.oerrors;
16687011737SAdrien Mazarguil }
16773bf9235SOphir Munk ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &tmp.imissed);
168c5193a0bSJiawei Wang if (ret == 0) {
169c5193a0bSJiawei Wang tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) &
170c5193a0bSJiawei Wang (uint64_t)UINT32_MAX;
171c5193a0bSJiawei Wang wrap_n = stats_ctrl->imissed >> 32;
172c5193a0bSJiawei Wang if (tmp.imissed < (stats_ctrl->imissed & (uint64_t)UINT32_MAX))
173c5193a0bSJiawei Wang wrap_n++;
174c5193a0bSJiawei Wang tmp.imissed |= (wrap_n) << 32;
175c5193a0bSJiawei Wang stats_ctrl->imissed = tmp.imissed;
176c5193a0bSJiawei Wang } else {
177c5193a0bSJiawei Wang tmp.imissed = stats_ctrl->imissed;
178c5193a0bSJiawei Wang }
17987011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
18087011737SAdrien Mazarguil /* FIXME: retrieve and add hardware counters. */
18187011737SAdrien Mazarguil #endif
18287011737SAdrien Mazarguil *stats = tmp;
183d5b0924bSMatan Azrad return 0;
18487011737SAdrien Mazarguil }
18587011737SAdrien Mazarguil
18687011737SAdrien Mazarguil /**
18787011737SAdrien Mazarguil * DPDK callback to clear device statistics.
18887011737SAdrien Mazarguil *
18987011737SAdrien Mazarguil * @param dev
19087011737SAdrien Mazarguil * Pointer to Ethernet device structure.
1919970a9adSIgor Romanov *
1929970a9adSIgor Romanov * @return
1939970a9adSIgor Romanov * always 0 on success and stats is reset
19487011737SAdrien Mazarguil */
1959970a9adSIgor Romanov int
mlx5_stats_reset(struct rte_eth_dev * dev)19687011737SAdrien Mazarguil mlx5_stats_reset(struct rte_eth_dev *dev)
19787011737SAdrien Mazarguil {
198dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
199ce9494d7STom Barbette struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
20087011737SAdrien Mazarguil unsigned int i;
20187011737SAdrien Mazarguil
20287011737SAdrien Mazarguil for (i = 0; (i != priv->rxqs_n); ++i) {
2035cf0707fSXueming Li struct mlx5_rxq_data *rxq_data = mlx5_rxq_data_get(dev, i);
2045cf0707fSXueming Li
2055cf0707fSXueming Li if (rxq_data == NULL)
20687011737SAdrien Mazarguil continue;
207773a7de2SRaja Zidane rxq_data->stats_reset = rxq_data->stats;
20887011737SAdrien Mazarguil }
20987011737SAdrien Mazarguil for (i = 0; (i != priv->txqs_n); ++i) {
210773a7de2SRaja Zidane struct mlx5_txq_data *txq_data = (*priv->txqs)[i];
211773a7de2SRaja Zidane
212773a7de2SRaja Zidane if (txq_data == NULL)
21387011737SAdrien Mazarguil continue;
214773a7de2SRaja Zidane txq_data->stats_reset = txq_data->stats;
21587011737SAdrien Mazarguil }
21673bf9235SOphir Munk mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
217c5193a0bSJiawei Wang stats_ctrl->imissed = 0;
21887011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
21987011737SAdrien Mazarguil /* FIXME: reset hardware counters. */
22087011737SAdrien Mazarguil #endif
2219970a9adSIgor Romanov
2229970a9adSIgor Romanov return 0;
22387011737SAdrien Mazarguil }
224a4193ae3SShahaf Shuler
225a4193ae3SShahaf Shuler /**
226a4193ae3SShahaf Shuler * DPDK callback to clear device extended statistics.
227a4193ae3SShahaf Shuler *
228a4193ae3SShahaf Shuler * @param dev
229a4193ae3SShahaf Shuler * Pointer to Ethernet device structure.
2309970a9adSIgor Romanov *
2319970a9adSIgor Romanov * @return
2329970a9adSIgor Romanov * 0 on success and stats is reset, negative errno value otherwise and
2339970a9adSIgor Romanov * rte_errno is set.
234a4193ae3SShahaf Shuler */
2359970a9adSIgor Romanov int
mlx5_xstats_reset(struct rte_eth_dev * dev)236a4193ae3SShahaf Shuler mlx5_xstats_reset(struct rte_eth_dev *dev)
237a4193ae3SShahaf Shuler {
238dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
239e62bc9e7SShahaf Shuler struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
240af4f09f2SNélio Laranjeiro unsigned int i;
24142dcd453SShiri Kuzin uint64_t *counters;
242a6d83b6aSNélio Laranjeiro int ret;
243*a687c3e6SBing Zhao uint16_t stats_n = 0;
244*a687c3e6SBing Zhao uint16_t stats_n_2nd = 0;
245*a687c3e6SBing Zhao bool bond_master = (priv->master && priv->pf_bond >= 0);
246a4193ae3SShahaf Shuler
247*a687c3e6SBing Zhao ret = mlx5_os_get_stats_n(dev, bond_master, &stats_n, &stats_n_2nd);
248*a687c3e6SBing Zhao if (ret < 0) {
249a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot get stats: %s", dev->data->port_id,
250*a687c3e6SBing Zhao strerror(-ret));
251*a687c3e6SBing Zhao return ret;
252a6d83b6aSNélio Laranjeiro }
253*a687c3e6SBing Zhao if (xstats_ctrl->stats_n != stats_n ||
254*a687c3e6SBing Zhao (bond_master && xstats_ctrl->stats_n_2nd != stats_n_2nd))
25573bf9235SOphir Munk mlx5_os_stats_init(dev);
256*a687c3e6SBing Zhao /* Considering to use stack directly. */
257*a687c3e6SBing Zhao counters = mlx5_malloc(MLX5_MEM_SYS, sizeof(*counters) * xstats_ctrl->mlx5_stats_n,
258*a687c3e6SBing Zhao 0, SOCKET_ID_ANY);
25942dcd453SShiri Kuzin if (!counters) {
260*a687c3e6SBing Zhao DRV_LOG(WARNING, "port %u unable to allocate memory for xstats counters",
26142dcd453SShiri Kuzin dev->data->port_id);
26242dcd453SShiri Kuzin rte_errno = ENOMEM;
26342dcd453SShiri Kuzin return -rte_errno;
26442dcd453SShiri Kuzin }
265*a687c3e6SBing Zhao ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
266a6d83b6aSNélio Laranjeiro if (ret) {
267a170a30dSNélio Laranjeiro DRV_LOG(ERR, "port %u cannot read device counters: %s",
2680f99970bSNélio Laranjeiro dev->data->port_id, strerror(rte_errno));
26942dcd453SShiri Kuzin mlx5_free(counters);
2709970a9adSIgor Romanov return ret;
271a6d83b6aSNélio Laranjeiro }
27242dcd453SShiri Kuzin for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
273af4f09f2SNélio Laranjeiro xstats_ctrl->base[i] = counters[i];
274c5193a0bSJiawei Wang xstats_ctrl->hw_stats[i] = 0;
275c5193a0bSJiawei Wang }
2763b025c0cSViacheslav Ovsiienko mlx5_txpp_xstats_reset(dev);
27742dcd453SShiri Kuzin mlx5_free(counters);
2789970a9adSIgor Romanov return 0;
279a4193ae3SShahaf Shuler }
280a4193ae3SShahaf Shuler
281a4193ae3SShahaf Shuler /**
282a4193ae3SShahaf Shuler * DPDK callback to retrieve names of extended device statistics
283a4193ae3SShahaf Shuler *
284a4193ae3SShahaf Shuler * @param dev
285a4193ae3SShahaf Shuler * Pointer to Ethernet device structure.
286a4193ae3SShahaf Shuler * @param[out] xstats_names
287a4193ae3SShahaf Shuler * Buffer to insert names into.
288a4193ae3SShahaf Shuler * @param n
289a4193ae3SShahaf Shuler * Number of names.
290a4193ae3SShahaf Shuler *
291a4193ae3SShahaf Shuler * @return
292a4193ae3SShahaf Shuler * Number of xstats names.
293a4193ae3SShahaf Shuler */
294a4193ae3SShahaf Shuler int
mlx5_xstats_get_names(struct rte_eth_dev * dev,struct rte_eth_xstat_name * xstats_names,unsigned int n)2953b025c0cSViacheslav Ovsiienko mlx5_xstats_get_names(struct rte_eth_dev *dev,
296a4193ae3SShahaf Shuler struct rte_eth_xstat_name *xstats_names, unsigned int n)
297a4193ae3SShahaf Shuler {
298a4193ae3SShahaf Shuler unsigned int i;
299dbeba4cfSThomas Monjalon struct mlx5_priv *priv = dev->data->dev_private;
3001a611fdaSShahaf Shuler struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
3011a611fdaSShahaf Shuler unsigned int mlx5_xstats_n = xstats_ctrl->mlx5_stats_n;
302a4193ae3SShahaf Shuler
3031a611fdaSShahaf Shuler if (n >= mlx5_xstats_n && xstats_names) {
3041a611fdaSShahaf Shuler for (i = 0; i != mlx5_xstats_n; ++i) {
305e1784075SDavid Marchand strlcpy(xstats_names[i].name,
3061a611fdaSShahaf Shuler xstats_ctrl->info[i].dpdk_name,
307a4193ae3SShahaf Shuler RTE_ETH_XSTATS_NAME_SIZE);
308a4193ae3SShahaf Shuler }
309a4193ae3SShahaf Shuler }
3103b025c0cSViacheslav Ovsiienko mlx5_xstats_n = mlx5_txpp_xstats_get_names(dev, xstats_names,
3113b025c0cSViacheslav Ovsiienko n, mlx5_xstats_n);
3121a611fdaSShahaf Shuler return mlx5_xstats_n;
313a4193ae3SShahaf Shuler }
314