1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2020 Mellanox Technologies, Ltd 3 */ 4 #include <stdio.h> 5 6 #include <rte_errno.h> 7 #include <rte_ether.h> 8 #include <ethdev_driver.h> 9 #include <rte_interrupts.h> 10 11 #include <mlx5_glue.h> 12 #include <mlx5_devx_cmds.h> 13 #include <mlx5_common.h> 14 #include <mlx5_win_ext.h> 15 #include <mlx5_malloc.h> 16 #include <mlx5.h> 17 #include <mlx5_utils.h> 18 19 /** 20 * Get MAC address by querying netdevice. 21 * 22 * @param[in] dev 23 * Pointer to Ethernet device. 24 * @param[out] mac 25 * MAC address output buffer. 26 * 27 * @return 28 * 0 on success, a negative errno value otherwise and rte_errno is set. 29 */ 30 int 31 mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[RTE_ETHER_ADDR_LEN]) 32 { 33 struct mlx5_priv *priv; 34 mlx5_context_st *context_obj; 35 36 if (!dev) { 37 rte_errno = EINVAL; 38 return -rte_errno; 39 } 40 priv = dev->data->dev_private; 41 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 42 memcpy(mac, context_obj->mlx5_dev.eth_mac, RTE_ETHER_ADDR_LEN); 43 return 0; 44 } 45 46 /** 47 * Get interface name from private structure. 48 * 49 * 50 * @param[in] dev 51 * Pointer to Ethernet device. 52 * @param[out] ifname 53 * Interface name output buffer. 54 * 55 * @return 56 * 0 on success, a negative errno value otherwise and rte_errno is set. 57 */ 58 int 59 mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[MLX5_NAMESIZE]) 60 { 61 struct mlx5_priv *priv; 62 mlx5_context_st *context_obj; 63 64 if (!dev) { 65 rte_errno = EINVAL; 66 return -rte_errno; 67 } 68 priv = dev->data->dev_private; 69 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 70 strncpy(*ifname, context_obj->mlx5_dev.name, MLX5_NAMESIZE); 71 return 0; 72 } 73 74 /** 75 * Get device MTU. 76 * 77 * @param dev 78 * Pointer to Ethernet device. 79 * @param[out] mtu 80 * MTU value output buffer. 81 * 82 * @return 83 * 0 on success, a negative errno value otherwise and rte_errno is set. 84 */ 85 int 86 mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu) 87 { 88 int err; 89 uint32_t curr_mtu; 90 struct mlx5_priv *priv; 91 mlx5_context_st *context_obj; 92 93 if (!dev) { 94 rte_errno = EINVAL; 95 return -rte_errno; 96 } 97 priv = dev->data->dev_private; 98 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 99 100 err = mlx5_glue->devx_get_mtu(context_obj, &curr_mtu); 101 if (err != 0) { 102 DRV_LOG(WARNING, "Could not get the MTU!"); 103 return err; 104 } 105 *mtu = (uint16_t)curr_mtu; 106 107 return 0; 108 } 109 110 /** 111 * Set device MTU. 112 * 113 * @param dev 114 * Pointer to Ethernet device. 115 * @param mtu 116 * MTU value to set. 117 * 118 * @return 119 * 0 on success, a negative errno value otherwise and rte_errno is set. 120 */ 121 int 122 mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) 123 { 124 int err; 125 struct mlx5_priv *priv; 126 mlx5_context_st *context_obj; 127 128 if (!dev) { 129 rte_errno = EINVAL; 130 return -rte_errno; 131 } 132 priv = dev->data->dev_private; 133 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 134 135 err = mlx5_glue->devx_set_mtu(context_obj, mtu); 136 if (err != 0) { 137 DRV_LOG(WARNING, "Could not set the MTU!"); 138 return err; 139 } 140 return 0; 141 } 142 143 /** 144 * DPDK callback to get flow control status. 145 * 146 * @param dev 147 * Pointer to Ethernet device structure. 148 * @param[out] fc_conf 149 * Flow control output buffer. 150 * 151 * @return 152 * 0 on success, a negative errno value otherwise and rte_errno is set. 153 */ 154 int 155 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 156 { 157 RTE_SET_USED(dev); 158 RTE_SET_USED(fc_conf); 159 return -ENOTSUP; 160 } 161 162 /** 163 * DPDK callback to modify flow control parameters. 164 * 165 * @param dev 166 * Pointer to Ethernet device structure. 167 * @param[in] fc_conf 168 * Flow control parameters. 169 * 170 * @return 171 * 0 on success, a negative errno value otherwise and rte_errno is set. 172 */ 173 int 174 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 175 { 176 RTE_SET_USED(dev); 177 RTE_SET_USED(fc_conf); 178 return -ENOTSUP; 179 } 180 181 /* 182 * Query the number of statistics provided by ETHTOOL. 183 * 184 * @param dev 185 * Pointer to Ethernet device. 186 * @param bond_master 187 * Indicate if the device is a bond master. 188 * @param n_stats 189 * Pointer to number of stats to store. 190 * @param n_stats_sec 191 * Pointer to number of stats to store for the 2nd port of the bond. 192 * 193 * @return 194 * 0 on success, negative errno value otherwise and rte_errno is set. 195 */ 196 int 197 mlx5_os_get_stats_n(struct rte_eth_dev *dev, bool bond_master, 198 uint16_t *n_stats, uint16_t *n_stats_sec) 199 { 200 RTE_SET_USED(dev); 201 RTE_SET_USED(bond_master); 202 RTE_SET_USED(n_stats); 203 RTE_SET_USED(n_stats_sec); 204 return -ENOTSUP; 205 } 206 207 /** 208 * Init the structures to read device counters. 209 * 210 * @param dev 211 * Pointer to Ethernet device. 212 */ 213 void 214 mlx5_os_stats_init(struct rte_eth_dev *dev) 215 { 216 struct mlx5_priv *priv = dev->data->dev_private; 217 struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl; 218 int ret; 219 220 /* Copy to base at first time. */ 221 ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base); 222 if (ret) 223 DRV_LOG(ERR, "port %u cannot read device counters: %s", 224 dev->data->port_id, strerror(rte_errno)); 225 stats_ctrl->imissed = 0; 226 } 227 228 /** 229 * Read device counters table. 230 * 231 * @param dev 232 * Pointer to Ethernet device. 233 * @param bond_master 234 * Indicate if the device is a bond master. 235 * @param[out] stats 236 * Counters table output buffer. 237 * 238 * @return 239 * 0 on success and stats is filled, negative errno value otherwise and 240 * rte_errno is set. 241 */ 242 int 243 mlx5_os_read_dev_counters(struct rte_eth_dev *dev, bool bond_master, uint64_t *stats) 244 { 245 RTE_SET_USED(dev); 246 RTE_SET_USED(bond_master); 247 RTE_SET_USED(stats); 248 return -ENOTSUP; 249 } 250 251 /** 252 * DPDK callback to retrieve physical link information. 253 * 254 * @param dev 255 * Pointer to Ethernet device structure. 256 * @param wait_to_complete 257 * Wait for request completion. 258 * 259 * @return 260 * 0 if link status was not updated, positive if it was, a negative errno 261 * value otherwise and rte_errno is set. 262 */ 263 int 264 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) 265 { 266 RTE_SET_USED(wait_to_complete); 267 struct mlx5_priv *priv; 268 mlx5_context_st *context_obj; 269 struct rte_eth_link dev_link; 270 int ret; 271 272 ret = 0; 273 if (!dev) { 274 rte_errno = EINVAL; 275 return -rte_errno; 276 } 277 priv = dev->data->dev_private; 278 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 279 dev_link.link_speed = context_obj->mlx5_dev.link_speed / (1000 * 1000); 280 dev_link.link_status = 281 (context_obj->mlx5_dev.link_state == 1 && !mlx5_is_removed(dev)) 282 ? 1 : 0; 283 dev_link.link_duplex = 1; 284 if (dev->data->dev_link.link_speed != dev_link.link_speed || 285 dev->data->dev_link.link_duplex != dev_link.link_duplex || 286 dev->data->dev_link.link_autoneg != dev_link.link_autoneg || 287 dev->data->dev_link.link_status != dev_link.link_status) 288 ret = 1; 289 else 290 ret = 0; 291 dev->data->dev_link = dev_link; 292 return ret; 293 } 294 295 /** 296 * DPDK callback to bring the link DOWN. 297 * 298 * @param dev 299 * Pointer to Ethernet device structure. 300 * 301 * @return 302 * 0 on success, a negative errno value otherwise 303 */ 304 int 305 mlx5_set_link_down(struct rte_eth_dev *dev) 306 { 307 RTE_SET_USED(dev); 308 return -ENOTSUP; 309 } 310 311 /** 312 * DPDK callback to bring the link UP. 313 * 314 * @param dev 315 * Pointer to Ethernet device structure. 316 * 317 * @return 318 * 0 on success, a negative errno value otherwise 319 */ 320 int 321 mlx5_set_link_up(struct rte_eth_dev *dev) 322 { 323 RTE_SET_USED(dev); 324 return -ENOTSUP; 325 } 326 327 /** 328 * DPDK callback to retrieve plug-in module EEPROM information (type and size). 329 * 330 * @param dev 331 * Pointer to Ethernet device structure. 332 * @param[out] modinfo 333 * Storage for plug-in module EEPROM information. 334 * 335 * @return 336 * 0 on success, a negative errno value otherwise and rte_errno is set. 337 */ 338 int 339 mlx5_get_module_info(struct rte_eth_dev *dev, 340 struct rte_eth_dev_module_info *modinfo) 341 { 342 RTE_SET_USED(dev); 343 RTE_SET_USED(modinfo); 344 return -ENOTSUP; 345 } 346 347 /** 348 * DPDK callback to retrieve plug-in module EEPROM data. 349 * 350 * @param dev 351 * Pointer to Ethernet device structure. 352 * @param[out] info 353 * Storage for plug-in module EEPROM data. 354 * 355 * @return 356 * 0 on success, a negative errno value otherwise and rte_errno is set. 357 */ 358 int mlx5_get_module_eeprom(struct rte_eth_dev *dev, 359 struct rte_dev_eeprom_info *info) 360 { 361 RTE_SET_USED(dev); 362 RTE_SET_USED(info); 363 return -ENOTSUP; 364 } 365 366 /** 367 * Get device current raw clock counter 368 * 369 * @param dev 370 * Pointer to Ethernet device structure. 371 * @param[out] time 372 * Current raw clock counter of the device. 373 * 374 * @return 375 * 0 if the clock has correctly been read 376 * The value of errno in case of error 377 */ 378 int 379 mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock) 380 { 381 int err; 382 struct mlx5_devx_clock mlx5_clock; 383 struct mlx5_priv *priv = dev->data->dev_private; 384 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 385 386 err = mlx5_glue->query_rt_values(context_obj, &mlx5_clock); 387 if (err != 0) { 388 DRV_LOG(WARNING, "Could not query the clock"); 389 return err; 390 } 391 *clock = *(uint64_t volatile *)mlx5_clock.p_iseg_internal_timer; 392 return 0; 393 } 394 395 /** 396 * Check if mlx5 device was removed. 397 * 398 * @param dev 399 * Pointer to Ethernet device structure. 400 * 401 * @return 402 * 1 when device is removed, otherwise 0. 403 */ 404 int 405 mlx5_is_removed(struct rte_eth_dev *dev) 406 { 407 struct mlx5_priv *priv = dev->data->dev_private; 408 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 409 410 if (*context_obj->shutdown_event_obj.p_flag) 411 return 1; 412 return 0; 413 } 414 415 /* 416 * Query dropless_rq private flag value provided by ETHTOOL. 417 * 418 * @param dev 419 * Pointer to Ethernet device. 420 * 421 * @return 422 * - 0 on success, flag is not set. 423 * - 1 on success, flag is set. 424 * - negative errno value otherwise and rte_errno is set. 425 */ 426 int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev) 427 { 428 RTE_SET_USED(dev); 429 return -ENOTSUP; 430 } 431 432 /** 433 * Unmaps HCA PCI BAR from the current process address space. 434 * 435 * @param dev 436 * Pointer to Ethernet device structure. 437 */ 438 void mlx5_txpp_unmap_hca_bar(struct rte_eth_dev *dev) 439 { 440 RTE_SET_USED(dev); 441 } 442 443 /** 444 * Maps HCA PCI BAR to the current process address space. 445 * Stores pointer in the process private structure allowing 446 * to read internal and real time counter directly from the HW. 447 * 448 * @param dev 449 * Pointer to Ethernet device structure. 450 * 451 * @return 452 * 0 on success and not NULL pointer to mapped area in process structure. 453 * negative otherwise and NULL pointer 454 */ 455 int mlx5_txpp_map_hca_bar(struct rte_eth_dev *dev) 456 { 457 RTE_SET_USED(dev); 458 rte_errno = ENOTSUP; 459 return -ENOTSUP; 460 } 461