X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_ethdev.c;h=d7d3bc73cec8431e1b33f1f4538c8b39f845b98c;hb=1b7b9f170fcebbbd0708fab554dcb5a7badef8cf;hp=5f05b2bb50ed112bb2b34ea31e6109c8d2c32753;hpb=06ee15784871cc457d62b6c965bc8cdac40f9703;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 5f05b2bb50..d7d3bc73ce 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -4,7 +4,6 @@ */ #include -#include #include #include #include @@ -36,8 +35,11 @@ #include #include +#include +#include +#include + #include "mlx5.h" -#include "mlx5_glue.h" #include "mlx5_rxtx.h" #include "mlx5_utils.h" @@ -138,7 +140,7 @@ mlx5_get_master_ifname(const char *ibdev_path, char (*ifname)[IF_NAMESIZE]) unsigned int dev_port_prev = ~0u; char match[IF_NAMESIZE] = ""; - assert(ibdev_path); + MLX5_ASSERT(ibdev_path); { MKSTR(path, "%s/device/net", ibdev_path); @@ -223,8 +225,8 @@ mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]) struct mlx5_priv *priv = dev->data->dev_private; unsigned int ifindex; - assert(priv); - assert(priv->sh); + MLX5_ASSERT(priv); + MLX5_ASSERT(priv->sh); ifindex = mlx5_ifindex(dev); if (!ifindex) { if (!priv->representor) @@ -254,8 +256,8 @@ mlx5_ifindex(const struct rte_eth_dev *dev) struct mlx5_priv *priv = dev->data->dev_private; unsigned int ifindex; - assert(priv); - assert(priv->if_index); + MLX5_ASSERT(priv); + MLX5_ASSERT(priv->if_index); ifindex = priv->if_index; if (!ifindex) rte_errno = ENXIO; @@ -383,9 +385,6 @@ mlx5_dev_configure(struct rte_eth_dev *dev) struct mlx5_priv *priv = dev->data->dev_private; unsigned int rxqs_n = dev->data->nb_rx_queues; unsigned int txqs_n = dev->data->nb_tx_queues; - unsigned int i; - unsigned int j; - unsigned int reta_idx_n; const uint8_t use_app_rss_key = !!dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key; int ret = 0; @@ -407,6 +406,10 @@ mlx5_dev_configure(struct rte_eth_dev *dev) rte_errno = ENOMEM; return -rte_errno; } + + if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) + dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH; + memcpy(priv->rss_conf.rss_key, use_app_rss_key ? dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key : @@ -431,34 +434,91 @@ mlx5_dev_configure(struct rte_eth_dev *dev) DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", dev->data->port_id, priv->rxqs_n, rxqs_n); priv->rxqs_n = rxqs_n; - /* - * If the requested number of RX queues is not a power of two, - * use the maximum indirection table size for better balancing. - * The result is always rounded to the next power of two. - */ - reta_idx_n = (1 << log2above((rxqs_n & (rxqs_n - 1)) ? - priv->config.ind_table_max_size : - rxqs_n)); - ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); - if (ret) - return ret; - /* - * When the number of RX queues is not a power of two, - * the remaining table entries are padded with reused WQs - * and hashes are not spread uniformly. - */ - for (i = 0, j = 0; (i != reta_idx_n); ++i) { - (*priv->reta_idx)[i] = j; - if (++j == rxqs_n) - j = 0; - } } + priv->skip_default_rss_reta = 0; ret = mlx5_proc_priv_init(dev); if (ret) return ret; return 0; } +/** + * Configure default RSS reta. + * + * @param dev + * Pointer to Ethernet device structure. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + unsigned int rxqs_n = dev->data->nb_rx_queues; + unsigned int i; + unsigned int j; + unsigned int reta_idx_n; + int ret = 0; + unsigned int *rss_queue_arr = NULL; + unsigned int rss_queue_n = 0; + + if (priv->skip_default_rss_reta) + return ret; + rss_queue_arr = rte_malloc("", rxqs_n * sizeof(unsigned int), 0); + if (!rss_queue_arr) { + DRV_LOG(ERR, "port %u cannot allocate RSS queue list (%u)", + dev->data->port_id, rxqs_n); + rte_errno = ENOMEM; + return -rte_errno; + } + for (i = 0, j = 0; i < rxqs_n; i++) { + struct mlx5_rxq_data *rxq_data; + struct mlx5_rxq_ctrl *rxq_ctrl; + + rxq_data = (*priv->rxqs)[i]; + rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq); + if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) + rss_queue_arr[j++] = i; + } + rss_queue_n = j; + if (rss_queue_n > priv->config.ind_table_max_size) { + DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u)", + dev->data->port_id, rss_queue_n); + rte_errno = EINVAL; + rte_free(rss_queue_arr); + return -rte_errno; + } + DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u", + dev->data->port_id, priv->rxqs_n, rxqs_n); + priv->rxqs_n = rxqs_n; + /* + * If the requested number of RX queues is not a power of two, + * use the maximum indirection table size for better balancing. + * The result is always rounded to the next power of two. + */ + reta_idx_n = (1 << log2above((rss_queue_n & (rss_queue_n - 1)) ? + priv->config.ind_table_max_size : + rss_queue_n)); + ret = mlx5_rss_reta_index_resize(dev, reta_idx_n); + if (ret) { + rte_free(rss_queue_arr); + return ret; + } + /* + * When the number of RX queues is not a power of two, + * the remaining table entries are padded with reused WQs + * and hashes are not spread uniformly. + */ + for (i = 0, j = 0; (i != reta_idx_n); ++i) { + (*priv->reta_idx)[i] = rss_queue_arr[j]; + if (++j == rss_queue_n) + j = 0; + } + rte_free(rss_queue_arr); + return ret; +} + /** * Sets default tuning parameters. * @@ -475,8 +535,8 @@ mlx5_set_default_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) /* Minimum CPU utilization. */ info->default_rxportconf.ring_size = 256; info->default_txportconf.ring_size = 256; - info->default_rxportconf.burst_size = 64; - info->default_txportconf.burst_size = 64; + info->default_rxportconf.burst_size = MLX5_RX_DEFAULT_BURST; + info->default_txportconf.burst_size = MLX5_TX_DEFAULT_BURST; if (priv->link_speed_capa & ETH_LINK_SPEED_100G) { info->default_rxportconf.nb_queues = 16; info->default_txportconf.nb_queues = 16; @@ -517,7 +577,7 @@ mlx5_set_txlimit_params(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) inlen = (config->txq_inline_max == MLX5_ARG_UNSET) ? MLX5_SEND_DEF_INLINE_LEN : (unsigned int)config->txq_inline_max; - assert(config->txq_inline_min >= 0); + MLX5_ASSERT(config->txq_inline_min >= 0); inlen = RTE_MAX(inlen, (unsigned int)config->txq_inline_min); inlen = RTE_MIN(inlen, MLX5_WQE_SIZE_MAX + MLX5_ESEG_MIN_INLINE_SIZE - @@ -552,15 +612,15 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) /* FIXME: we should ask the device for these values. */ info->min_rx_bufsize = 32; info->max_rx_pktlen = 65536; + info->max_lro_pkt_size = MLX5_MAX_LRO_SIZE; /* * Since we need one CQ per QP, the limit is the minimum number * between the two values. */ max = RTE_MIN(priv->sh->device_attr.orig_attr.max_cq, priv->sh->device_attr.orig_attr.max_qp); - /* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */ - if (max >= 65535) - max = 65535; + /* max_rx_queues is uint16_t. */ + max = RTE_MIN(max, (unsigned int)UINT16_MAX); info->max_rx_queues = max; info->max_tx_queues = max; info->max_mac_addrs = MLX5_MAX_UC_MAC_ADDRESSES; @@ -595,7 +655,7 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info) priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) { DRV_LOG(ERR, "can't update switch port ID" " for bonding device"); - assert(false); + MLX5_ASSERT(false); return -ENODEV; } info->switch_info.port_id |= @@ -733,7 +793,7 @@ mlx5_find_master_dev(struct rte_eth_dev *dev) priv = dev->data->dev_private; domain_id = priv->domain_id; - assert(priv->representor); + MLX5_ASSERT(priv->representor); MLX5_ETH_FOREACH_DEV(port_id, priv->pci_dev) { struct mlx5_priv *opriv = rte_eth_devices[port_id].data->dev_private; @@ -1150,58 +1210,6 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf) return 0; } -/** - * Get PCI information by sysfs device path. - * - * @param dev_path - * Pointer to device sysfs folder name. - * @param[out] pci_addr - * PCI bus address output buffer. - * - * @return - * 0 on success, a negative errno value otherwise and rte_errno is set. - */ -int -mlx5_dev_to_pci_addr(const char *dev_path, - struct rte_pci_addr *pci_addr) -{ - FILE *file; - char line[32]; - MKSTR(path, "%s/device/uevent", dev_path); - - file = fopen(path, "rb"); - if (file == NULL) { - rte_errno = errno; - return -rte_errno; - } - while (fgets(line, sizeof(line), file) == line) { - size_t len = strlen(line); - int ret; - - /* Truncate long lines. */ - if (len == (sizeof(line) - 1)) - while (line[(len - 1)] != '\n') { - ret = fgetc(file); - if (ret == EOF) - break; - line[(len - 1)] = ret; - } - /* Extract information. */ - if (sscanf(line, - "PCI_SLOT_NAME=" - "%" SCNx32 ":%" SCNx8 ":%" SCNx8 ".%" SCNx8 "\n", - &pci_addr->domain, - &pci_addr->bus, - &pci_addr->devid, - &pci_addr->function) == 4) { - ret = 0; - break; - } - } - fclose(file); - return 0; -} - /** * Handle asynchronous removal event for entire multiport device. * @@ -1224,7 +1232,7 @@ mlx5_dev_interrupt_device_fatal(struct mlx5_ibv_shared *sh) continue; } dev = &rte_eth_devices[sh->port[i].ih_port_id]; - assert(dev); + MLX5_ASSERT(dev); if (dev->data->dev_conf.intr_conf.rmv) _rte_eth_dev_callback_process (dev, RTE_ETH_EVENT_INTR_RMV, NULL); @@ -1263,7 +1271,7 @@ mlx5_dev_interrupt_handler(void *cb_arg) mlx5_dev_interrupt_device_fatal(sh); continue; } - assert(tmp && (tmp <= sh->max_port)); + MLX5_ASSERT(tmp && (tmp <= sh->max_port)); if (!tmp) { /* Unsupported devive level event. */ mlx5_glue->ack_async_event(&event); @@ -1293,7 +1301,7 @@ mlx5_dev_interrupt_handler(void *cb_arg) /* Retrieve ethernet device descriptor. */ tmp = sh->port[tmp - 1].ih_port_id; dev = &rte_eth_devices[tmp]; - assert(dev); + MLX5_ASSERT(dev); if ((event.event_type == IBV_EVENT_PORT_ACTIVE || event.event_type == IBV_EVENT_PORT_ERR) && dev->data->dev_conf.intr_conf.lsc) { @@ -1348,7 +1356,7 @@ mlx5_intr_callback_unregister(const struct rte_intr_handle *handle, if (ret != -EAGAIN) { DRV_LOG(INFO, "failed to unregister interrupt" " handler (error: %d)", ret); - assert(false); + MLX5_ASSERT(false); return; } if (twait) { @@ -1369,7 +1377,7 @@ mlx5_intr_callback_unregister(const struct rte_intr_handle *handle, * on first iteration. */ twait = rte_get_timer_hz(); - assert(twait); + MLX5_ASSERT(twait); } /* * Timeout elapsed, show message (once a second) and retry. @@ -1433,14 +1441,14 @@ mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return; pthread_mutex_lock(&sh->intr_mutex); - assert(priv->ibv_port); - assert(priv->ibv_port <= sh->max_port); - assert(dev->data->port_id < RTE_MAX_ETHPORTS); + MLX5_ASSERT(priv->ibv_port); + MLX5_ASSERT(priv->ibv_port <= sh->max_port); + MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS); if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS) goto exit; - assert(sh->port[priv->ibv_port - 1].ih_port_id == + MLX5_ASSERT(sh->port[priv->ibv_port - 1].ih_port_id == (uint32_t)dev->data->port_id); - assert(sh->intr_cnt); + MLX5_ASSERT(sh->intr_cnt); sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; if (!sh->intr_cnt || --sh->intr_cnt) goto exit; @@ -1448,6 +1456,37 @@ mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev) mlx5_dev_interrupt_handler, sh); sh->intr_handle.fd = 0; sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; +exit: + pthread_mutex_unlock(&sh->intr_mutex); +} + +/** + * Uninstall devx shared asynchronous device events handler. + * This function is implemeted to support event sharing + * between multiple ports of single IB device. + * + * @param dev + * Pointer to Ethernet device. + */ +static void +mlx5_dev_shared_handler_devx_uninstall(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_ibv_shared *sh = priv->sh; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + pthread_mutex_lock(&sh->intr_mutex); + MLX5_ASSERT(priv->ibv_port); + MLX5_ASSERT(priv->ibv_port <= sh->max_port); + MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS); + if (sh->port[priv->ibv_port - 1].devx_ih_port_id >= RTE_MAX_ETHPORTS) + goto exit; + MLX5_ASSERT(sh->port[priv->ibv_port - 1].devx_ih_port_id == + (uint32_t)dev->data->port_id); + sh->port[priv->ibv_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS; + if (!sh->devx_intr_cnt || --sh->devx_intr_cnt) + goto exit; if (sh->intr_handle_devx.fd) { rte_intr_callback_unregister(&sh->intr_handle_devx, mlx5_dev_interrupt_handler_devx, @@ -1482,70 +1521,100 @@ mlx5_dev_shared_handler_install(struct rte_eth_dev *dev) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return; pthread_mutex_lock(&sh->intr_mutex); - assert(priv->ibv_port); - assert(priv->ibv_port <= sh->max_port); - assert(dev->data->port_id < RTE_MAX_ETHPORTS); + MLX5_ASSERT(priv->ibv_port); + MLX5_ASSERT(priv->ibv_port <= sh->max_port); + MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS); if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) { /* The handler is already installed for this port. */ - assert(sh->intr_cnt); + MLX5_ASSERT(sh->intr_cnt); goto exit; } - sh->port[priv->ibv_port - 1].ih_port_id = (uint32_t)dev->data->port_id; if (sh->intr_cnt) { + sh->port[priv->ibv_port - 1].ih_port_id = + (uint32_t)dev->data->port_id; sh->intr_cnt++; goto exit; } /* No shared handler installed. */ - assert(sh->ctx->async_fd > 0); + MLX5_ASSERT(sh->ctx->async_fd > 0); flags = fcntl(sh->ctx->async_fd, F_GETFL); ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK); if (ret) { - DRV_LOG(INFO, "failed to change file descriptor" - " async event queue"); - goto error; + DRV_LOG(INFO, "failed to change file descriptor async event" + " queue"); + /* Indicate there will be no interrupts. */ + dev->data->dev_conf.intr_conf.lsc = 0; + dev->data->dev_conf.intr_conf.rmv = 0; + } else { + sh->intr_handle.fd = sh->ctx->async_fd; + sh->intr_handle.type = RTE_INTR_HANDLE_EXT; + rte_intr_callback_register(&sh->intr_handle, + mlx5_dev_interrupt_handler, sh); + sh->intr_cnt++; + sh->port[priv->ibv_port - 1].ih_port_id = + (uint32_t)dev->data->port_id; + } +exit: + pthread_mutex_unlock(&sh->intr_mutex); +} + +/** + * Install devx shared asyncronous device events handler. + * This function is implemeted to support event sharing + * between multiple ports of single IB device. + * + * @param dev + * Pointer to Ethernet device. + */ +static void +mlx5_dev_shared_handler_devx_install(struct rte_eth_dev *dev) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_ibv_shared *sh = priv->sh; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + pthread_mutex_lock(&sh->intr_mutex); + MLX5_ASSERT(priv->ibv_port); + MLX5_ASSERT(priv->ibv_port <= sh->max_port); + MLX5_ASSERT(dev->data->port_id < RTE_MAX_ETHPORTS); + if (sh->port[priv->ibv_port - 1].devx_ih_port_id < RTE_MAX_ETHPORTS) { + /* The handler is already installed for this port. */ + MLX5_ASSERT(sh->devx_intr_cnt); + goto exit; + } + if (sh->devx_intr_cnt) { + sh->devx_intr_cnt++; + sh->port[priv->ibv_port - 1].devx_ih_port_id = + (uint32_t)dev->data->port_id; + goto exit; } - sh->intr_handle.fd = sh->ctx->async_fd; - sh->intr_handle.type = RTE_INTR_HANDLE_EXT; - rte_intr_callback_register(&sh->intr_handle, - mlx5_dev_interrupt_handler, sh); if (priv->config.devx) { #ifndef HAVE_IBV_DEVX_ASYNC - goto error_unregister; + goto exit; #else sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx); if (sh->devx_comp) { - flags = fcntl(sh->devx_comp->fd, F_GETFL); - ret = fcntl(sh->devx_comp->fd, F_SETFL, + int flags = fcntl(sh->devx_comp->fd, F_GETFL); + int ret = fcntl(sh->devx_comp->fd, F_SETFL, flags | O_NONBLOCK); + if (ret) { DRV_LOG(INFO, "failed to change file descriptor" - " devx async event queue"); - goto error_unregister; + " devx async event queue"); + } else { + sh->intr_handle_devx.fd = sh->devx_comp->fd; + sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT; + rte_intr_callback_register + (&sh->intr_handle_devx, + mlx5_dev_interrupt_handler_devx, sh); + sh->devx_intr_cnt++; + sh->port[priv->ibv_port - 1].devx_ih_port_id = + (uint32_t)dev->data->port_id; } - sh->intr_handle_devx.fd = sh->devx_comp->fd; - sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT; - rte_intr_callback_register - (&sh->intr_handle_devx, - mlx5_dev_interrupt_handler_devx, sh); - } else { - DRV_LOG(INFO, "failed to create devx async command " - "completion"); - goto error_unregister; } #endif /* HAVE_IBV_DEVX_ASYNC */ } - sh->intr_cnt++; - goto exit; -error_unregister: - rte_intr_callback_unregister(&sh->intr_handle, - mlx5_dev_interrupt_handler, sh); -error: - /* Indicate there will be no interrupts. */ - dev->data->dev_conf.intr_conf.lsc = 0; - dev->data->dev_conf.intr_conf.rmv = 0; - sh->intr_handle.fd = 0; - sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; - sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS; exit: pthread_mutex_unlock(&sh->intr_mutex); } @@ -1574,6 +1643,30 @@ mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev) mlx5_dev_shared_handler_install(dev); } +/** + * Devx uninstall interrupt handler. + * + * @param dev + * Pointer to Ethernet device. + */ +void +mlx5_dev_interrupt_handler_devx_uninstall(struct rte_eth_dev *dev) +{ + mlx5_dev_shared_handler_devx_uninstall(dev); +} + +/** + * Devx install interrupt handler. + * + * @param dev + * Pointer to Ethernet device. + */ +void +mlx5_dev_interrupt_handler_devx_install(struct rte_eth_dev *dev) +{ + mlx5_dev_shared_handler_devx_install(dev); +} + /** * DPDK callback to bring the link DOWN. * @@ -1618,7 +1711,7 @@ mlx5_select_rx_function(struct rte_eth_dev *dev) { eth_rx_burst_t rx_pkt_burst = mlx5_rx_burst; - assert(dev != NULL); + MLX5_ASSERT(dev != NULL); if (mlx5_check_vec_rx_support(dev) > 0) { rx_pkt_burst = mlx5_rx_burst_vec; DRV_LOG(DEBUG, "port %u selected Rx vectorized function", @@ -1654,6 +1747,10 @@ mlx5_is_removed(struct rte_eth_dev *dev) * * @param[in] port * Device port id. + * @param[in] valid + * Device port id is valid, skip check. This flag is useful + * when trials are performed from probing and device is not + * flagged as valid yet (in attaching process). * @param[out] es_domain_id * E-Switch domain id. * @param[out] es_port_id @@ -1664,7 +1761,7 @@ mlx5_is_removed(struct rte_eth_dev *dev) * on success, NULL otherwise and rte_errno is set. */ struct mlx5_priv * -mlx5_port_to_eswitch_info(uint16_t port) +mlx5_port_to_eswitch_info(uint16_t port, bool valid) { struct rte_eth_dev *dev; struct mlx5_priv *priv; @@ -1673,7 +1770,7 @@ mlx5_port_to_eswitch_info(uint16_t port) rte_errno = EINVAL; return NULL; } - if (!rte_eth_dev_is_valid_port(port)) { + if (!valid && !rte_eth_dev_is_valid_port(port)) { rte_errno = ENODEV; return NULL; } @@ -1781,7 +1878,7 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) mlx5_sysfs_check_switch_info(device_dir, &data); } *info = data; - assert(!(data.master && data.representor)); + MLX5_ASSERT(!(data.master && data.representor)); if (data.master && data.representor) { DRV_LOG(ERR, "ifindex %u device is recognized as master" " and as representor", ifindex); @@ -1791,55 +1888,6 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) return 0; } -/** - * Analyze gathered port parameters via Netlink to recognize master - * and representor devices for E-Switch configuration. - * - * @param[in] num_vf_set - * flag of presence of number of VFs port attribute. - * @param[inout] switch_info - * Port information, including port name as a number and port name - * type if recognized - * - * @return - * master and representor flags are set in switch_info according to - * recognized parameters (if any). - */ -void -mlx5_nl_check_switch_info(bool num_vf_set, - struct mlx5_switch_info *switch_info) -{ - switch (switch_info->name_type) { - case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: - /* - * Name is not recognized, assume the master, - * check the number of VFs key presence. - */ - switch_info->master = num_vf_set; - break; - case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: - /* - * Name is not set, this assumes the legacy naming - * schema for master, just check if there is a - * number of VFs key. - */ - switch_info->master = num_vf_set; - break; - case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: - /* New uplink naming schema recognized. */ - switch_info->master = 1; - break; - case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: - /* Legacy representors naming schema. */ - switch_info->representor = !num_vf_set; - break; - case MLX5_PHYS_PORT_NAME_TYPE_PFVF: - /* New representors naming schema. */ - switch_info->representor = 1; - break; - } -} - /** * Analyze gathered port parameters via sysfs to recognize master * and representor devices for E-Switch configuration. @@ -1889,61 +1937,6 @@ mlx5_sysfs_check_switch_info(bool device_dir, } } -/** - * Extract port name, as a number, from sysfs or netlink information. - * - * @param[in] port_name_in - * String representing the port name. - * @param[out] port_info_out - * Port information, including port name as a number and port name - * type if recognized - * - * @return - * port_name field set according to recognized name format. - */ -void -mlx5_translate_port_name(const char *port_name_in, - struct mlx5_switch_info *port_info_out) -{ - char pf_c1, pf_c2, vf_c1, vf_c2; - char *end; - int sc_items; - - /* - * Check for port-name as a string of the form pf0vf0 - * (support kernel ver >= 5.0 or OFED ver >= 4.6). - */ - sc_items = sscanf(port_name_in, "%c%c%d%c%c%d", - &pf_c1, &pf_c2, &port_info_out->pf_num, - &vf_c1, &vf_c2, &port_info_out->port_name); - if (sc_items == 6 && - pf_c1 == 'p' && pf_c2 == 'f' && - vf_c1 == 'v' && vf_c2 == 'f') { - port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF; - return; - } - /* - * Check for port-name as a string of the form p0 - * (support kernel ver >= 5.0, or OFED ver >= 4.6). - */ - sc_items = sscanf(port_name_in, "%c%d", - &pf_c1, &port_info_out->port_name); - if (sc_items == 2 && pf_c1 == 'p') { - port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK; - return; - } - /* Check for port-name as a number (support kernel ver < 5.0 */ - errno = 0; - port_info_out->port_name = strtol(port_name_in, &end, 0); - if (!errno && - (size_t)(end - port_name_in) == strlen(port_name_in)) { - port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY; - return; - } - port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; - return; -} - /** * DPDK callback to retrieve plug-in module EEPROM information (type and size). * @@ -2029,3 +2022,30 @@ int mlx5_get_module_eeprom(struct rte_eth_dev *dev, rte_free(eeprom); return ret; } + +/** + * DPDK callback to retrieve hairpin capabilities. + * + * @param dev + * Pointer to Ethernet device structure. + * @param[out] cap + * Storage for hairpin capability data. + * + * @return + * 0 on success, a negative errno value otherwise and rte_errno is set. + */ +int mlx5_hairpin_cap_get(struct rte_eth_dev *dev, + struct rte_eth_hairpin_cap *cap) +{ + struct mlx5_priv *priv = dev->data->dev_private; + + if (priv->sh->devx == 0) { + rte_errno = ENOTSUP; + return -rte_errno; + } + cap->max_nb_queues = UINT16_MAX; + cap->max_rx_2_tx = 1; + cap->max_tx_2_rx = 1; + cap->max_nb_desc = 8192; + return 0; +}