#endif
}
+/**
+ * DR flow drop action support detect.
+ *
+ * @param dev
+ * Pointer to rte_eth_dev structure.
+ *
+ */
+static void
+mlx5_flow_drop_action_config(struct rte_eth_dev *dev __rte_unused)
+{
+#ifdef HAVE_MLX5DV_DR
+ struct mlx5_priv *priv = dev->data->dev_private;
+
+ if (!priv->config.dv_flow_en || !priv->sh->dr_drop_action)
+ return;
+ /**
+ * DR supports drop action placeholder when it is supported;
+ * otherwise, use the queue drop action.
+ */
+ if (mlx5_flow_discover_dr_action_support(dev))
+ priv->root_drop_action = priv->drop_queue.hrxq->action;
+ else
+ priv->root_drop_action = priv->sh->dr_drop_action;
+#endif
+}
+
static void
mlx5_queue_counter_id_prepare(struct rte_eth_dev *dev)
{
err = mlx5_proc_priv_init(eth_dev);
if (err)
return NULL;
- mp_id.port_id = eth_dev->data->port_id;
- strlcpy(mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN);
+ mlx5_mp_id_init(&mp_id, eth_dev->data->port_id);
/* Receive command fd from primary process */
err = mlx5_mp_req_verbs_cmd_fd(&mp_id);
if (err < 0)
priv->vport_meta_tag = 0;
priv->vport_meta_mask = 0;
priv->pf_bond = spawn->pf_bond;
+
+ DRV_LOG(DEBUG,
+ "dev_port=%u bus=%s pci=%s master=%d representor=%d pf_bond=%d\n",
+ priv->dev_port, dpdk_dev->bus->name,
+ priv->pci_dev ? priv->pci_dev->name : "NONE",
+ priv->master, priv->representor, priv->pf_bond);
+
/*
* If we have E-Switch we should determine the vport attributes.
* E-Switch may use either source vport field or reg_c[0] metadata
* Look for sibling devices in order to reuse their switch domain
* if any, otherwise allocate one.
*/
- MLX5_ETH_FOREACH_DEV(port_id, NULL) {
+ MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
const struct mlx5_priv *opriv =
rte_eth_devices[port_id].data->dev_private;
RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
continue;
priv->domain_id = opriv->domain_id;
+ DRV_LOG(DEBUG, "dev_port-%u inherit domain_id=%u\n",
+ priv->dev_port, priv->domain_id);
break;
}
if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
goto error;
}
own_domain_id = 1;
+ DRV_LOG(DEBUG, "dev_port-%u new domain_id=%u\n",
+ priv->dev_port, priv->domain_id);
}
/* Override some values set by hardware configuration. */
mlx5_args(config, dpdk_dev->devargs);
- err = mlx5_dev_check_sibling_config(priv, config);
+ err = mlx5_dev_check_sibling_config(priv, config, dpdk_dev);
if (err)
goto error;
config->hw_csum = !!(sh->device_attr.device_cap_flags_ex &
if (priv->representor) {
eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
eth_dev->data->representor_id = priv->representor_id;
+ MLX5_ETH_FOREACH_DEV(port_id, dpdk_dev) {
+ struct mlx5_priv *opriv =
+ rte_eth_devices[port_id].data->dev_private;
+ if (opriv &&
+ opriv->master &&
+ opriv->domain_id == priv->domain_id &&
+ opriv->sh == priv->sh) {
+ eth_dev->data->backer_port_id = port_id;
+ break;
+ }
+ }
+ if (port_id >= RTE_MAX_ETHPORTS)
+ eth_dev->data->backer_port_id = eth_dev->data->port_id;
}
priv->mp_id.port_id = eth_dev->data->port_id;
strlcpy(priv->mp_id.name, MLX5_MP_NAME, RTE_MP_MAX_NAME_LEN);
goto error;
}
DRV_LOG(INFO,
- "port %u MAC address is %02x:%02x:%02x:%02x:%02x:%02x",
- eth_dev->data->port_id,
- mac.addr_bytes[0], mac.addr_bytes[1],
- mac.addr_bytes[2], mac.addr_bytes[3],
- mac.addr_bytes[4], mac.addr_bytes[5]);
+ "port %u MAC address is " RTE_ETHER_ADDR_PRT_FMT,
+ eth_dev->data->port_id, RTE_ETHER_ADDR_BYTES(&mac));
#ifdef RTE_LIBRTE_MLX5_DEBUG
{
char ifname[MLX5_NAMESIZE];
} else {
priv->obj_ops = ibv_obj_ops;
}
+ if (config->tx_pp &&
+ (priv->config.dv_esw_en ||
+ priv->obj_ops.txq_obj_new != mlx5_os_txq_obj_new)) {
+ /*
+ * HAVE_MLX5DV_DEVX_UAR_OFFSET is required to support
+ * packet pacing and already checked above.
+ * Hence, we should only make sure the SQs will be created
+ * with DevX, not with Verbs.
+ * Verbs allocates the SQ UAR on its own and it can't be shared
+ * with Clock Queue UAR as required for Tx scheduling.
+ */
+ DRV_LOG(ERR, "Verbs SQs, UAR can't be shared as required for packet pacing");
+ err = ENODEV;
+ goto error;
+ }
priv->drop_queue.hrxq = mlx5_drop_action_create(eth_dev);
if (!priv->drop_queue.hrxq)
goto error;
}
rte_spinlock_init(&priv->shared_act_sl);
mlx5_flow_counter_mode_config(eth_dev);
+ mlx5_flow_drop_action_config(eth_dev);
if (priv->config.dv_flow_en)
eth_dev->data->dev_flags |= RTE_ETH_DEV_FLOW_OPS_THREAD_SAFE;
return eth_dev;
config->txqs_inline = MLX5_ARG_UNSET;
config->vf_nl_en = 1;
config->mr_ext_memseg_en = 1;
+ config->mr_mempool_reg_en = 1;
config->mprq.max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN;
config->mprq.min_rxqs_num = MLX5_MPRQ_MIN_RXQS;
config->dv_esw_en = 1;
config->dv_flow_en = 1;
config->decap_en = 1;
config->log_hp_size = MLX5_ARG_UNSET;
+ config->allow_duplicate_pattern = 1;
}
/**
goto exit;
}
}
-#ifndef HAVE_MLX5DV_DR_DEVX_PORT
- if (bd >= 0) {
- /*
- * This may happen if there is VF LAG kernel support and
- * application is compiled with older rdma_core library.
- */
- DRV_LOG(ERR,
- "No kernel/verbs support for VF LAG bonding found.");
- rte_errno = ENOTSUP;
- ret = -rte_errno;
- goto exit;
- }
-#endif
/*
* Now we can determine the maximal
* amount of devices to be spawned.
(list[ns].ifindex,
&list[ns].info);
}
-#ifdef HAVE_MLX5DV_DR_DEVX_PORT
if (!ret && bd >= 0) {
switch (list[ns].info.name_type) {
case MLX5_PHYS_PORT_NAME_TYPE_UPLINK:
+ if (np == 1) {
+ /*
+ * Force standalone bonding
+ * device for ROCE LAG
+ * confgiurations.
+ */
+ list[ns].info.master = 0;
+ list[ns].info.representor = 0;
+ }
if (list[ns].info.port_name == bd)
ns++;
break;
}
continue;
}
-#endif
if (!ret && (list[ns].info.representor ^
list[ns].info.master))
ns++;
/* Default configuration. */
mlx5_os_config_default(&dev_config);
dev_config.vf = dev_config_vf;
- dev_config.allow_duplicate_pattern = 1;
list[i].numa_node = pci_dev->device.numa_node;
list[i].eth_dev = mlx5_dev_spawn(&pci_dev->device,
&list[i],
}
restore = list[i].eth_dev->data->dev_flags;
rte_eth_copy_pci_info(list[i].eth_dev, pci_dev);
+ /**
+ * Each representor has a dedicated interrupts vector.
+ * rte_eth_copy_pci_info() assigns PF interrupts handle to
+ * representor eth_dev object because representor and PF
+ * share the same PCI address.
+ * Override representor device with a dedicated
+ * interrupts handle here.
+ * Representor interrupts handle is released in mlx5_dev_stop().
+ */
+ if (list[i].info.representor) {
+ struct rte_intr_handle *intr_handle;
+ intr_handle = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO,
+ sizeof(*intr_handle), 0,
+ SOCKET_ID_ANY);
+ if (!intr_handle) {
+ DRV_LOG(ERR,
+ "port %u failed to allocate memory for interrupt handler "
+ "Rx interrupts will not be supported",
+ i);
+ rte_errno = ENOMEM;
+ ret = -rte_errno;
+ goto exit;
+ }
+ list[i].eth_dev->intr_handle = intr_handle;
+ }
/* Restore non-PCI flags cleared by the above call. */
list[i].eth_dev->data->dev_flags |= restore;
rte_eth_dev_probing_finish(list[i].eth_dev);
if (eth_da.nb_ports > 0) {
/* Iterate all port if devargs pf is range: "pf[0-1]vf[...]". */
- for (p = 0; p < eth_da.nb_ports; p++)
+ for (p = 0; p < eth_da.nb_ports; p++) {
ret = mlx5_os_pci_probe_pf(pci_dev, ð_da,
eth_da.ports[p]);
+ if (ret)
+ break;
+ }
+ if (ret) {
+ DRV_LOG(ERR, "Probe of PCI device " PCI_PRI_FMT " "
+ "aborted due to proding failure of PF %u",
+ pci_dev->addr.domain, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function,
+ eth_da.ports[p]);
+ mlx5_net_remove(&pci_dev->device);
+ }
} else {
ret = mlx5_os_pci_probe_pf(pci_dev, ð_da, 0);
}