Branch data Line data Source code
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 : 0 : mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats, 39 : : unsigned int n) 40 : 0 : { 41 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 42 : : unsigned int i; 43 : 0 : uint64_t counters[n]; 44 : : struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl; 45 : 0 : uint16_t mlx5_stats_n = xstats_ctrl->mlx5_stats_n; 46 : : 47 [ # # # # ]: 0 : if (n >= mlx5_stats_n && stats) { 48 : : int stats_n; 49 : : int ret; 50 : : 51 : 0 : stats_n = mlx5_os_get_stats_n(dev); 52 [ # # ]: 0 : if (stats_n < 0) 53 : : return stats_n; 54 [ # # ]: 0 : if (xstats_ctrl->stats_n != stats_n) 55 : 0 : mlx5_os_stats_init(dev); 56 : 0 : ret = mlx5_os_read_dev_counters(dev, counters); 57 [ # # ]: 0 : if (ret) 58 : : return ret; 59 [ # # ]: 0 : for (i = 0; i != mlx5_stats_n; ++i) { 60 : 0 : stats[i].id = i; 61 [ # # ]: 0 : if (xstats_ctrl->info[i].dev) { 62 : : uint64_t wrap_n; 63 : 0 : uint64_t hw_stat = xstats_ctrl->hw_stats[i]; 64 : : 65 : 0 : stats[i].value = (counters[i] - 66 : 0 : xstats_ctrl->base[i]) & 67 : : (uint64_t)UINT32_MAX; 68 : 0 : wrap_n = hw_stat >> 32; 69 : 0 : if (stats[i].value < 70 [ # # ]: 0 : (hw_stat & (uint64_t)UINT32_MAX)) 71 : 0 : wrap_n++; 72 : 0 : stats[i].value |= (wrap_n) << 32; 73 : 0 : xstats_ctrl->hw_stats[i] = stats[i].value; 74 : : } else { 75 : 0 : stats[i].value = 76 : 0 : (counters[i] - xstats_ctrl->base[i]); 77 : : } 78 : : } 79 : : } 80 : 0 : mlx5_stats_n = mlx5_txpp_xstats_get(dev, stats, n, mlx5_stats_n); 81 : 0 : 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 : 0 : mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) 98 : : { 99 : 0 : 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 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); ++i) { 110 : 0 : struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, i); 111 : : 112 [ # # ]: 0 : if (rxq == NULL) 113 : 0 : continue; 114 : 0 : idx = rxq->idx; 115 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 116 : : #ifdef MLX5_PMD_SOFT_COUNTERS 117 : 0 : tmp.q_ipackets[idx] += rxq->stats.ipackets - 118 : 0 : rxq->stats_reset.ipackets; 119 : 0 : tmp.q_ibytes[idx] += rxq->stats.ibytes - 120 : 0 : rxq->stats_reset.ibytes; 121 : : #endif 122 : 0 : tmp.q_errors[idx] += (rxq->stats.idropped + 123 : 0 : rxq->stats.rx_nombuf) - 124 : 0 : (rxq->stats_reset.idropped + 125 : 0 : rxq->stats_reset.rx_nombuf); 126 : : } 127 : : #ifdef MLX5_PMD_SOFT_COUNTERS 128 : 0 : tmp.ipackets += rxq->stats.ipackets - rxq->stats_reset.ipackets; 129 : 0 : tmp.ibytes += rxq->stats.ibytes - rxq->stats_reset.ibytes; 130 : : #endif 131 : 0 : tmp.ierrors += rxq->stats.idropped - rxq->stats_reset.idropped; 132 : 0 : tmp.rx_nombuf += rxq->stats.rx_nombuf - 133 : 0 : rxq->stats_reset.rx_nombuf; 134 : : } 135 [ # # ]: 0 : for (i = 0; (i != priv->txqs_n); ++i) { 136 : 0 : struct mlx5_txq_data *txq = (*priv->txqs)[i]; 137 : : 138 [ # # ]: 0 : if (txq == NULL) 139 : 0 : continue; 140 : 0 : idx = txq->idx; 141 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) { 142 : : #ifdef MLX5_PMD_SOFT_COUNTERS 143 : 0 : tmp.q_opackets[idx] += txq->stats.opackets - 144 : 0 : txq->stats_reset.opackets; 145 : 0 : tmp.q_obytes[idx] += txq->stats.obytes - 146 : 0 : txq->stats_reset.obytes; 147 : : #endif 148 : : } 149 : : #ifdef MLX5_PMD_SOFT_COUNTERS 150 : 0 : tmp.opackets += txq->stats.opackets - txq->stats_reset.opackets; 151 : 0 : tmp.obytes += txq->stats.obytes - txq->stats_reset.obytes; 152 : : #endif 153 : 0 : tmp.oerrors += txq->stats.oerrors - txq->stats_reset.oerrors; 154 : : } 155 : 0 : ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &tmp.imissed); 156 [ # # ]: 0 : if (ret == 0) { 157 : 0 : tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) & 158 : : (uint64_t)UINT32_MAX; 159 : 0 : wrap_n = stats_ctrl->imissed >> 32; 160 [ # # ]: 0 : if (tmp.imissed < (stats_ctrl->imissed & (uint64_t)UINT32_MAX)) 161 : 0 : wrap_n++; 162 : 0 : tmp.imissed |= (wrap_n) << 32; 163 : 0 : stats_ctrl->imissed = tmp.imissed; 164 : : } else { 165 : 0 : tmp.imissed = stats_ctrl->imissed; 166 : : } 167 : : #ifndef MLX5_PMD_SOFT_COUNTERS 168 : : /* FIXME: retrieve and add hardware counters. */ 169 : : #endif 170 : 0 : *stats = tmp; 171 : 0 : 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 : 0 : mlx5_stats_reset(struct rte_eth_dev *dev) 185 : : { 186 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 187 : : struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl; 188 : : unsigned int i; 189 : : 190 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); ++i) { 191 : 0 : struct mlx5_rxq_data *rxq_data = mlx5_rxq_data_get(dev, i); 192 : : 193 [ # # ]: 0 : if (rxq_data == NULL) 194 : 0 : continue; 195 : 0 : rxq_data->stats_reset = rxq_data->stats; 196 : : } 197 [ # # ]: 0 : for (i = 0; (i != priv->txqs_n); ++i) { 198 : 0 : struct mlx5_txq_data *txq_data = (*priv->txqs)[i]; 199 : : 200 [ # # ]: 0 : if (txq_data == NULL) 201 : 0 : continue; 202 : 0 : txq_data->stats_reset = txq_data->stats; 203 : : } 204 : 0 : mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base); 205 : 0 : stats_ctrl->imissed = 0; 206 : : #ifndef MLX5_PMD_SOFT_COUNTERS 207 : : /* FIXME: reset hardware counters. */ 208 : : #endif 209 : : 210 : 0 : 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 : 0 : mlx5_xstats_reset(struct rte_eth_dev *dev) 225 : : { 226 : 0 : 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 : 0 : stats_n = mlx5_os_get_stats_n(dev); 234 [ # # ]: 0 : if (stats_n < 0) { 235 : 0 : DRV_LOG(ERR, "port %u cannot get stats: %s", dev->data->port_id, 236 : : strerror(-stats_n)); 237 : 0 : return stats_n; 238 : : } 239 [ # # ]: 0 : if (xstats_ctrl->stats_n != stats_n) 240 : 0 : mlx5_os_stats_init(dev); 241 : 0 : counters = mlx5_malloc(MLX5_MEM_SYS, sizeof(*counters) * 242 : 0 : xstats_ctrl->mlx5_stats_n, 0, 243 : : SOCKET_ID_ANY); 244 [ # # ]: 0 : if (!counters) { 245 : 0 : DRV_LOG(WARNING, "port %u unable to allocate memory for xstats " 246 : : "counters", 247 : : dev->data->port_id); 248 : 0 : rte_errno = ENOMEM; 249 : 0 : return -rte_errno; 250 : : } 251 : 0 : ret = mlx5_os_read_dev_counters(dev, counters); 252 [ # # ]: 0 : if (ret) { 253 : 0 : DRV_LOG(ERR, "port %u cannot read device counters: %s", 254 : : dev->data->port_id, strerror(rte_errno)); 255 : 0 : mlx5_free(counters); 256 : 0 : return ret; 257 : : } 258 [ # # ]: 0 : for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) { 259 : 0 : xstats_ctrl->base[i] = counters[i]; 260 : 0 : xstats_ctrl->hw_stats[i] = 0; 261 : : } 262 : 0 : mlx5_txpp_xstats_reset(dev); 263 : 0 : mlx5_free(counters); 264 : 0 : 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 : 0 : 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 : 0 : struct mlx5_priv *priv = dev->data->dev_private; 286 : : struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl; 287 : 0 : unsigned int mlx5_xstats_n = xstats_ctrl->mlx5_stats_n; 288 : : 289 [ # # ]: 0 : if (n >= mlx5_xstats_n && xstats_names) { 290 [ # # ]: 0 : for (i = 0; i != mlx5_xstats_n; ++i) { 291 : 0 : strlcpy(xstats_names[i].name, 292 : : xstats_ctrl->info[i].dpdk_name, 293 : : RTE_ETH_XSTATS_NAME_SIZE); 294 : : } 295 : : } 296 : 0 : mlx5_xstats_n = mlx5_txpp_xstats_get_names(dev, xstats_names, 297 : : n, mlx5_xstats_n); 298 : 0 : return mlx5_xstats_n; 299 : : }