*/
#include <stddef.h>
-#include <assert.h>
#include <inttypes.h>
#include <unistd.h>
#include <stdbool.h>
#include <rte_rwlock.h>
#include <rte_cycles.h>
+#include <mlx5_glue.h>
+#include <mlx5_devx_cmds.h>
+#include <mlx5_common.h>
+
#include "mlx5.h"
-#include "mlx5_glue.h"
#include "mlx5_rxtx.h"
#include "mlx5_utils.h"
unsigned int dev_port_prev = ~0u;
char match[IF_NAMESIZE] = "";
- assert(ibdev_path);
+ MLX5_ASSERT(ibdev_path);
{
MKSTR(path, "%s/device/net", ibdev_path);
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)
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;
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;
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 :
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.
*
/* 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;
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 -
/* 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;
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 |=
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;
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.
*
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);
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);
/* 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) {
if (ret != -EAGAIN) {
DRV_LOG(INFO, "failed to unregister interrupt"
" handler (error: %d)", ret);
- assert(false);
+ MLX5_ASSERT(false);
return;
}
if (twait) {
* on first iteration.
*/
twait = rte_get_timer_hz();
- assert(twait);
+ MLX5_ASSERT(twait);
}
/*
* Timeout elapsed, show message (once a second) and retry.
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;
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,
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);
}
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.
*
{
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",
*
* @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
* 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;
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;
}
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);
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.
}
}
-/**
- * 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).
*
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;
+}