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 * Unregister callback handler safely. The handler may be active 145 * while we are trying to unregister it, in this case code -EAGAIN 146 * is returned by rte_intr_callback_unregister(). This routine checks 147 * the return code and tries to unregister handler again. 148 * 149 * @param handle 150 * interrupt handle 151 * @param cb_fn 152 * pointer to callback routine 153 * @cb_arg 154 * opaque callback parameter 155 */ 156 void 157 mlx5_intr_callback_unregister(const struct rte_intr_handle *handle, 158 rte_intr_callback_fn cb_fn, void *cb_arg) 159 { 160 RTE_SET_USED(handle); 161 RTE_SET_USED(cb_fn); 162 RTE_SET_USED(cb_arg); 163 } 164 165 /** 166 * DPDK callback to get flow control status. 167 * 168 * @param dev 169 * Pointer to Ethernet device structure. 170 * @param[out] fc_conf 171 * Flow control output buffer. 172 * 173 * @return 174 * 0 on success, a negative errno value otherwise and rte_errno is set. 175 */ 176 int 177 mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 178 { 179 RTE_SET_USED(dev); 180 RTE_SET_USED(fc_conf); 181 return -ENOTSUP; 182 } 183 184 /** 185 * DPDK callback to modify flow control parameters. 186 * 187 * @param dev 188 * Pointer to Ethernet device structure. 189 * @param[in] fc_conf 190 * Flow control parameters. 191 * 192 * @return 193 * 0 on success, a negative errno value otherwise and rte_errno is set. 194 */ 195 int 196 mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) 197 { 198 RTE_SET_USED(dev); 199 RTE_SET_USED(fc_conf); 200 return -ENOTSUP; 201 } 202 203 /** 204 * Query the number of statistics provided by ETHTOOL. 205 * 206 * @param dev 207 * Pointer to Ethernet device. 208 * 209 * @return 210 * Number of statistics on success, negative errno value otherwise and 211 * rte_errno is set. 212 */ 213 int 214 mlx5_os_get_stats_n(struct rte_eth_dev *dev) 215 { 216 RTE_SET_USED(dev); 217 return -ENOTSUP; 218 } 219 220 /** 221 * Init the structures to read device counters. 222 * 223 * @param dev 224 * Pointer to Ethernet device. 225 */ 226 void 227 mlx5_os_stats_init(struct rte_eth_dev *dev) 228 { 229 struct mlx5_priv *priv = dev->data->dev_private; 230 struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl; 231 int ret; 232 233 /* Copy to base at first time. */ 234 ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base); 235 if (ret) 236 DRV_LOG(ERR, "port %u cannot read device counters: %s", 237 dev->data->port_id, strerror(rte_errno)); 238 stats_ctrl->imissed = 0; 239 } 240 241 /** 242 * Read device counters table. 243 * 244 * @param dev 245 * Pointer to Ethernet device. 246 * @param[out] stats 247 * Counters table output buffer. 248 * 249 * @return 250 * 0 on success and stats is filled, negative errno value otherwise and 251 * rte_errno is set. 252 */ 253 int 254 mlx5_os_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats) 255 { 256 RTE_SET_USED(dev); 257 RTE_SET_USED(stats); 258 return -ENOTSUP; 259 } 260 261 /** 262 * DPDK callback to retrieve physical link information. 263 * 264 * @param dev 265 * Pointer to Ethernet device structure. 266 * @param wait_to_complete 267 * Wait for request completion. 268 * 269 * @return 270 * 0 if link status was not updated, positive if it was, a negative errno 271 * value otherwise and rte_errno is set. 272 */ 273 int 274 mlx5_link_update(struct rte_eth_dev *dev, int wait_to_complete) 275 { 276 RTE_SET_USED(wait_to_complete); 277 struct mlx5_priv *priv; 278 mlx5_context_st *context_obj; 279 struct rte_eth_link dev_link; 280 int ret; 281 282 ret = 0; 283 if (!dev) { 284 rte_errno = EINVAL; 285 return -rte_errno; 286 } 287 priv = dev->data->dev_private; 288 context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 289 dev_link.link_speed = context_obj->mlx5_dev.link_speed / (1000 * 1000); 290 dev_link.link_status = 291 (context_obj->mlx5_dev.link_state == 1 && !mlx5_is_removed(dev)) 292 ? 1 : 0; 293 dev_link.link_duplex = 1; 294 if (dev->data->dev_link.link_speed != dev_link.link_speed || 295 dev->data->dev_link.link_duplex != dev_link.link_duplex || 296 dev->data->dev_link.link_autoneg != dev_link.link_autoneg || 297 dev->data->dev_link.link_status != dev_link.link_status) 298 ret = 1; 299 else 300 ret = 0; 301 dev->data->dev_link = dev_link; 302 return ret; 303 } 304 305 /** 306 * DPDK callback to bring the link DOWN. 307 * 308 * @param dev 309 * Pointer to Ethernet device structure. 310 * 311 * @return 312 * 0 on success, a negative errno value otherwise 313 */ 314 int 315 mlx5_set_link_down(struct rte_eth_dev *dev) 316 { 317 RTE_SET_USED(dev); 318 return -ENOTSUP; 319 } 320 321 /** 322 * DPDK callback to bring the link UP. 323 * 324 * @param dev 325 * Pointer to Ethernet device structure. 326 * 327 * @return 328 * 0 on success, a negative errno value otherwise 329 */ 330 int 331 mlx5_set_link_up(struct rte_eth_dev *dev) 332 { 333 RTE_SET_USED(dev); 334 return -ENOTSUP; 335 } 336 337 /** 338 * DPDK callback to retrieve plug-in module EEPROM information (type and size). 339 * 340 * @param dev 341 * Pointer to Ethernet device structure. 342 * @param[out] modinfo 343 * Storage for plug-in module EEPROM information. 344 * 345 * @return 346 * 0 on success, a negative errno value otherwise and rte_errno is set. 347 */ 348 int 349 mlx5_get_module_info(struct rte_eth_dev *dev, 350 struct rte_eth_dev_module_info *modinfo) 351 { 352 RTE_SET_USED(dev); 353 RTE_SET_USED(modinfo); 354 return -ENOTSUP; 355 } 356 357 /** 358 * DPDK callback to retrieve plug-in module EEPROM data. 359 * 360 * @param dev 361 * Pointer to Ethernet device structure. 362 * @param[out] info 363 * Storage for plug-in module EEPROM data. 364 * 365 * @return 366 * 0 on success, a negative errno value otherwise and rte_errno is set. 367 */ 368 int mlx5_get_module_eeprom(struct rte_eth_dev *dev, 369 struct rte_dev_eeprom_info *info) 370 { 371 RTE_SET_USED(dev); 372 RTE_SET_USED(info); 373 return -ENOTSUP; 374 } 375 376 /** 377 * Get device current raw clock counter 378 * 379 * @param dev 380 * Pointer to Ethernet device structure. 381 * @param[out] time 382 * Current raw clock counter of the device. 383 * 384 * @return 385 * 0 if the clock has correctly been read 386 * The value of errno in case of error 387 */ 388 int 389 mlx5_read_clock(struct rte_eth_dev *dev, uint64_t *clock) 390 { 391 int err; 392 struct mlx5_devx_clock mlx5_clock; 393 struct mlx5_priv *priv = dev->data->dev_private; 394 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 395 396 err = mlx5_glue->query_rt_values(context_obj, &mlx5_clock); 397 if (err != 0) { 398 DRV_LOG(WARNING, "Could not query the clock"); 399 return err; 400 } 401 *clock = *(uint64_t volatile *)mlx5_clock.p_iseg_internal_timer; 402 return 0; 403 } 404 405 /** 406 * Check if mlx5 device was removed. 407 * 408 * @param dev 409 * Pointer to Ethernet device structure. 410 * 411 * @return 412 * 1 when device is removed, otherwise 0. 413 */ 414 int 415 mlx5_is_removed(struct rte_eth_dev *dev) 416 { 417 struct mlx5_priv *priv = dev->data->dev_private; 418 mlx5_context_st *context_obj = (mlx5_context_st *)priv->sh->cdev->ctx; 419 420 if (*context_obj->shutdown_event_obj.p_flag) 421 return 1; 422 return 0; 423 } 424 425 /* 426 * Query dropless_rq private flag value provided by ETHTOOL. 427 * 428 * @param dev 429 * Pointer to Ethernet device. 430 * 431 * @return 432 * - 0 on success, flag is not set. 433 * - 1 on success, flag is set. 434 * - negative errno value otherwise and rte_errno is set. 435 */ 436 int mlx5_get_flag_dropless_rq(struct rte_eth_dev *dev) 437 { 438 RTE_SET_USED(dev); 439 return -ENOTSUP; 440 } 441