Move open IBV/DevX device function to common.
Signed-off-by: Michael Baum <michaelba@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
#include "mlx5_common.h"
#include "mlx5_common_log.h"
+#include "mlx5_common_defs.h"
#include "mlx5_common_os.h"
#include "mlx5_glue.h"
mlx5_glue->free_device_list(ibv_list);
return ibv_match;
}
+
+static int
+mlx5_config_doorbell_mapping_env(int dbnc)
+{
+ char *env;
+ int value;
+
+ MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+ /* Get environment variable to store. */
+ env = getenv(MLX5_SHUT_UP_BF);
+ value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET;
+ if (dbnc == MLX5_ARG_UNSET)
+ setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1);
+ else
+ setenv(MLX5_SHUT_UP_BF,
+ dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1);
+ return value;
+}
+
+static void
+mlx5_restore_doorbell_mapping_env(int value)
+{
+ MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
+ /* Restore the original environment variable state. */
+ if (value == MLX5_ARG_UNSET)
+ unsetenv(MLX5_SHUT_UP_BF);
+ else
+ setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
+}
+
+/**
+ * Function API to open IB device.
+ *
+ *
+ * @param cdev
+ * Pointer to the mlx5 device.
+ * @param ctx_ptr
+ * Pointer to fill inside pointer to device context.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx_ptr)
+{
+ struct ibv_device *ibv;
+ struct ibv_context *ctx = NULL;
+ int dbmap_env;
+
+ ibv = mlx5_os_get_ibv_dev(cdev->dev);
+ if (!ibv)
+ return -rte_errno;
+ DRV_LOG(INFO, "Dev information matches for device \"%s\".", ibv->name);
+ /*
+ * Configure environment variable "MLX5_BF_SHUT_UP" before the device
+ * creation. The rdma_core library checks the variable at device
+ * creation and stores the result internally.
+ */
+ dbmap_env = mlx5_config_doorbell_mapping_env(cdev->config.dbnc);
+ /* Try to open IB device with DV first, then usual Verbs. */
+ errno = 0;
+ ctx = mlx5_glue->dv_open_device(ibv);
+ if (ctx) {
+ cdev->config.devx = 1;
+ DRV_LOG(DEBUG, "DevX is supported.");
+ } else {
+ /* The environment variable is still configured. */
+ ctx = mlx5_glue->open_device(ibv);
+ if (ctx == NULL)
+ goto error;
+ DRV_LOG(DEBUG, "DevX is NOT supported.");
+ }
+ /* The device is created, no need for environment. */
+ mlx5_restore_doorbell_mapping_env(dbmap_env);
+ /* Hint libmlx5 to use PMD allocator for data plane resources */
+ mlx5_set_context_attr(cdev->dev, ctx);
+ *ctx_ptr = (void *)ctx;
+ return 0;
+error:
+ rte_errno = errno ? errno : ENODEV;
+ /* The device creation is failed, no need for environment. */
+ mlx5_restore_doorbell_mapping_env(dbmap_env);
+ DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name);
+ return -rte_errno;
+}
struct ibv_device *
mlx5_os_get_ibv_dev(const struct rte_device *dev);
+void
+mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx);
+
#endif /* RTE_PMD_MLX5_COMMON_OS_H_ */
#include <rte_errno.h>
#include <rte_bus_pci.h>
+#include <rte_eal_paging.h>
#include <rte_bus_auxiliary.h>
#include "mlx5_common_utils.h"
#include "mlx5_common_private.h"
#include "mlx5_autoconf.h"
#include <mlx5_glue.h>
+#include <mlx5_malloc.h>
#include <mlx5_common.h>
#include <mlx5_common_mr.h>
return ibv;
}
+/**
+ * Verbs callback to allocate a memory. This function should allocate the space
+ * according to the size provided residing inside a huge page.
+ * Please note that all allocation must respect the alignment from libmlx5
+ * (i.e. currently rte_mem_page_size()).
+ *
+ * @param[in] size
+ * The size in bytes of the memory to allocate.
+ * @param[in] data
+ * A pointer to the callback data.
+ *
+ * @return
+ * Allocated buffer, NULL otherwise and rte_errno is set.
+ */
+static void *
+mlx5_alloc_verbs_buf(size_t size, void *data)
+{
+ struct rte_device *dev = data;
+ void *ret;
+ size_t alignment = rte_mem_page_size();
+ if (alignment == (size_t)-1) {
+ DRV_LOG(ERR, "Failed to get mem page size");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+
+ MLX5_ASSERT(data != NULL);
+ ret = mlx5_malloc(0, size, alignment, dev->numa_node);
+ if (!ret && size)
+ rte_errno = ENOMEM;
+ return ret;
+}
+
+/**
+ * Verbs callback to free a memory.
+ *
+ * @param[in] ptr
+ * A pointer to the memory to free.
+ * @param[in] data
+ * A pointer to the callback data.
+ */
+static void
+mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
+{
+ MLX5_ASSERT(data != NULL);
+ mlx5_free(ptr);
+}
+
+/**
+ * Hint libmlx5 to use PMD allocator for data plane resources.
+ *
+ * @param dev
+ * Pointer to the generic device.
+ */
+void
+mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx)
+{
+ struct mlx5dv_ctx_allocators allocator = {
+ .alloc = &mlx5_alloc_verbs_buf,
+ .free = &mlx5_free_verbs_buf,
+ .data = dev,
+ };
+
+ /* Hint libmlx5 to use PMD allocator for data plane resources */
+ mlx5_glue->dv_set_context_attr(ctx, MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
+ (void *)((uintptr_t)&allocator));
+}
+
/**
* Register mr. Given protection domain pointer, pointer to addr and length
* register the memory region.
*/
struct mlx5_common_dev_config {
int dbnc; /* Skip doorbell register write barrier. */
+ unsigned int devx:1; /* Whether devx interface is available or not. */
unsigned int sys_mem_en:1; /* The default memory allocator. */
unsigned int mr_mempool_reg_en:1;
/* Allow/prevent implicit mempool memory registration. */
bool
mlx5_dev_is_pci(const struct rte_device *dev);
+/* mlx5_common_os.c */
+
+__rte_internal
+int mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx);
+
#endif /* RTE_PMD_MLX5_COMMON_H_ */
mlx5_os_dealloc_pd;
mlx5_os_dereg_mr;
mlx5_os_get_ibv_dev; # WINDOWS_NO_EXPORT
+ mlx5_os_open_device;
mlx5_os_reg_mr;
mlx5_os_umem_dereg;
mlx5_os_umem_reg;
return 0;
}
+/**
+ * Detect if a devx_device_bdf object has identical DBDF values to the
+ * rte_pci_addr found in bus/pci probing.
+ *
+ * @param[in] devx_bdf
+ * Pointer to the devx_device_bdf structure.
+ * @param[in] addr
+ * Pointer to the rte_pci_addr structure.
+ *
+ * @return
+ * 1 on Device match, 0 on mismatch.
+ */
+static int
+mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
+ struct rte_pci_addr *addr)
+{
+ if (addr->domain != (devx_bdf->bus_id >> 8) ||
+ addr->bus != (devx_bdf->bus_id & 0xff) ||
+ addr->devid != devx_bdf->dev_id ||
+ addr->function != devx_bdf->fnc_id) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Detect if a devx_device_bdf object matches the rte_pci_addr
+ * found in bus/pci probing
+ * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
+ *
+ * @param[in] devx_bdf
+ * Pointer to the devx_device_bdf structure.
+ * @param[in] addr
+ * Pointer to the rte_pci_addr structure.
+ *
+ * @return
+ * 1 on Device match, 0 on mismatch, rte_errno code on failure.
+ */
+static int
+mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
+ struct rte_pci_addr *addr)
+{
+ int err;
+ struct devx_device mlx5_dev;
+
+ if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
+ return 1;
+ /*
+ * Didn't match on Native/PF BDF, could still match a VF BDF,
+ * check it next.
+ */
+ err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
+ if (err) {
+ DRV_LOG(ERR, "query_device failed");
+ rte_errno = err;
+ return rte_errno;
+ }
+ if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
+ return 1;
+ return 0;
+}
+
+/**
+ * Look for DevX device that match to given rte_device.
+ *
+ * @param dev
+ * Pointer to the generic device.
+ * @param devx_list
+ * Pointer to head of DevX devices list.
+ * @param n
+ * Number of devices in given DevX devices list.
+ *
+ * @return
+ * A device match on success, NULL otherwise and rte_errno is set.
+ */
+static struct devx_device_bdf *
+mlx5_os_get_devx_device(struct rte_device *dev,
+ struct devx_device_bdf *devx_list, int n)
+{
+ struct devx_device_bdf *devx_match = NULL;
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
+ struct rte_pci_addr *addr = &pci_dev->addr;
+
+ while (n-- > 0) {
+ int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
+ if (!ret) {
+ devx_list++;
+ continue;
+ }
+ if (ret != 1) {
+ rte_errno = ret;
+ return NULL;
+ }
+ devx_match = devx_list;
+ break;
+ }
+ if (devx_match == NULL) {
+ /* No device matches, just complain and bail out. */
+ DRV_LOG(WARNING,
+ "No DevX device matches PCI device " PCI_PRI_FMT ","
+ " is DevX Configured?",
+ addr->domain, addr->bus, addr->devid, addr->function);
+ rte_errno = ENOENT;
+ }
+ return devx_match;
+}
+
+/**
+ * Function API open device under Windows.
+ *
+ * This function calls the Windows glue APIs to open a device.
+ *
+ * @param dev
+ * Pointer to mlx5 device structure.
+ * @param ctx
+ * Pointer to fill inside pointer to device context.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_open_device(struct mlx5_common_device *cdev, void **ctx)
+{
+ struct devx_device_bdf *devx_bdf_dev = NULL;
+ struct devx_device_bdf *devx_list;
+ struct mlx5_context *mlx5_ctx = NULL;
+ int n;
+
+ errno = 0;
+ devx_list = mlx5_glue->get_device_list(&n);
+ if (devx_list == NULL) {
+ rte_errno = errno ? errno : ENOSYS;
+ DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
+ return -rte_errno;
+ }
+ devx_bdf_dev = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
+ if (devx_bdf_dev == NULL)
+ goto error;
+ /* Try to open DevX device with DV. */
+ mlx5_ctx = mlx5_glue->open_device(devx_bdf_dev);
+ if (mlx5_ctx == NULL) {
+ DRV_LOG(ERR, "Failed to open DevX device.");
+ rte_errno = errno;
+ goto error;
+ }
+ if (mlx5_glue->query_device(devx_bdf_dev, &mlx5_ctx->mlx5_dev)) {
+ DRV_LOG(ERR, "Failed to query device context fields.");
+ rte_errno = errno;
+ goto error;
+ }
+ cdev->config.devx = 1;
+ *ctx = (void *)mlx5_ctx;
+ mlx5_glue->free_device_list(devx_list);
+ return 0;
+error:
+ if (mlx5_ctx != NULL)
+ claim_zero(mlx5_glue->close_device(mlx5_ctx));
+ mlx5_glue->free_device_list(devx_list);
+ return -rte_errno;
+}
+
/**
* Register umem.
*
return err;
}
-/**
- * Verbs callback to allocate a memory. This function should allocate the space
- * according to the size provided residing inside a huge page.
- * Please note that all allocation must respect the alignment from libmlx5
- * (i.e. currently rte_mem_page_size()).
- *
- * @param[in] size
- * The size in bytes of the memory to allocate.
- * @param[in] data
- * A pointer to the callback data.
- *
- * @return
- * Allocated buffer, NULL otherwise and rte_errno is set.
- */
-static void *
-mlx5_alloc_verbs_buf(size_t size, void *data)
-{
- struct mlx5_dev_ctx_shared *sh = data;
- void *ret;
- size_t alignment = rte_mem_page_size();
- if (alignment == (size_t)-1) {
- DRV_LOG(ERR, "Failed to get mem page size");
- rte_errno = ENOMEM;
- return NULL;
- }
-
- MLX5_ASSERT(data != NULL);
- ret = mlx5_malloc(0, size, alignment, sh->numa_node);
- if (!ret && size)
- rte_errno = ENOMEM;
- return ret;
-}
-
/**
* Detect misc5 support or not
*
}
#endif
-/**
- * Verbs callback to free a memory.
- *
- * @param[in] ptr
- * A pointer to the memory to free.
- * @param[in] data
- * A pointer to the callback data.
- */
-static void
-mlx5_free_verbs_buf(void *ptr, void *data __rte_unused)
-{
- MLX5_ASSERT(data != NULL);
- mlx5_free(ptr);
-}
-
/**
* Initialize DR related data within private structure.
* Routine checks the reference counter and does actual
* Verbs device parameters (name, port, switch_info) to spawn.
* @param config
* Device configuration parameters.
- * @param config
+ * @param eth_da
* Device arguments.
*
* @return
/* Bonding device. */
if (!switch_info->representor) {
err = snprintf(name, sizeof(name), "%s_%s",
- dpdk_dev->name,
- mlx5_os_get_dev_device_name(spawn->phys_dev));
+ dpdk_dev->name, spawn->phys_dev_name);
} else {
err = snprintf(name, sizeof(name), "%s_%s_representor_c%dpf%d%s%u",
- dpdk_dev->name,
- mlx5_os_get_dev_device_name(spawn->phys_dev),
+ dpdk_dev->name, spawn->phys_dev_name,
switch_info->ctrl_num,
switch_info->pf_num,
switch_info->name_type ==
&vport_info);
if (err) {
DRV_LOG(WARNING,
- "can't query devx port %d on device %s",
- spawn->phys_port,
- mlx5_os_get_dev_device_name(spawn->phys_dev));
+ "Cannot query devx port %d on device %s",
+ spawn->phys_port, spawn->phys_dev_name);
vport_info.query_flags = 0;
}
}
priv->vport_meta_tag = vport_info.vport_meta_tag;
priv->vport_meta_mask = vport_info.vport_meta_mask;
if (!priv->vport_meta_mask) {
- DRV_LOG(ERR, "vport zero mask for port %d"
- " on bonding device %s",
- spawn->phys_port,
- mlx5_os_get_dev_device_name
- (spawn->phys_dev));
+ DRV_LOG(ERR,
+ "vport zero mask for port %d on bonding device %s",
+ spawn->phys_port, spawn->phys_dev_name);
err = ENOTSUP;
goto error;
}
if (priv->vport_meta_tag & ~priv->vport_meta_mask) {
- DRV_LOG(ERR, "invalid vport tag for port %d"
- " on bonding device %s",
- spawn->phys_port,
- mlx5_os_get_dev_device_name
- (spawn->phys_dev));
+ DRV_LOG(ERR,
+ "Invalid vport tag for port %d on bonding device %s",
+ spawn->phys_port, spawn->phys_dev_name);
err = ENOTSUP;
goto error;
}
priv->vport_id = vport_info.vport_id;
} else if (spawn->pf_bond >= 0 &&
(switch_info->representor || switch_info->master)) {
- DRV_LOG(ERR, "can't deduce vport index for port %d"
- " on bonding device %s",
- spawn->phys_port,
- mlx5_os_get_dev_device_name(spawn->phys_dev));
+ DRV_LOG(ERR,
+ "Cannot deduce vport index for port %d on bonding device %s",
+ spawn->phys_port, spawn->phys_dev_name);
err = ENOTSUP;
goto error;
} else {
priv->mtr_profile_tbl = mlx5_l3t_create(MLX5_L3T_TYPE_PTR);
if (!priv->mtr_profile_tbl)
goto error;
- /* Hint libmlx5 to use PMD allocator for data plane resources */
- mlx5_glue->dv_set_context_attr(sh->ctx,
- MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
- (void *)((uintptr_t)&(struct mlx5dv_ctx_allocators){
- .alloc = &mlx5_alloc_verbs_buf,
- .free = &mlx5_free_verbs_buf,
- .data = sh,
- }));
/* Bring Ethernet device up. */
DRV_LOG(DEBUG, "port %u forcing Ethernet interface up",
eth_dev->data->port_id);
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
static int
-mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev,
+mlx5_os_pci_probe_pf(struct mlx5_common_device *cdev, void *ctx,
struct rte_eth_devargs *req_eth_da,
uint16_t owner_id)
{
ibv_list = mlx5_glue->get_device_list(&ret);
if (!ibv_list) {
rte_errno = errno ? errno : ENOSYS;
- DRV_LOG(ERR, "cannot list devices, is ib_uverbs loaded?");
+ DRV_LOG(ERR, "Cannot list devices, is ib_uverbs loaded?");
return -rte_errno;
}
/*
while (ret-- > 0) {
struct rte_pci_addr pci_addr;
- DRV_LOG(DEBUG, "checking device \"%s\"", ibv_list[ret]->name);
+ DRV_LOG(DEBUG, "Checking device \"%s\"", ibv_list[ret]->name);
bd = mlx5_device_bond_pci_match
(ibv_list[ret], &owner_pci, nl_rdma, owner_id,
&bond_info);
if (!nd) {
/* No device matches, just complain and bail out. */
DRV_LOG(WARNING,
- "no Verbs device matches PCI device " PCI_PRI_FMT ","
+ "No Verbs device matches PCI device " PCI_PRI_FMT ","
" are kernel drivers loaded?",
owner_pci.domain, owner_pci.bus,
owner_pci.devid, owner_pci.function);
if (nl_rdma >= 0)
np = mlx5_nl_portnum(nl_rdma, ibv_match[0]->name);
if (!np)
- DRV_LOG(WARNING, "can not get IB device \"%s\""
- " ports number", ibv_match[0]->name);
+ DRV_LOG(WARNING,
+ "Cannot get IB device \"%s\" ports number.",
+ ibv_match[0]->name);
if (bd >= 0 && !np) {
- DRV_LOG(ERR, "can not get ports"
- " for bonding device");
+ DRV_LOG(ERR, "Cannot get ports for bonding device.");
rte_errno = ENOENT;
ret = -rte_errno;
goto exit;
}
}
- /*
- * Now we can determine the maximal
- * amount of devices to be spawned.
- */
+ /* Now we can determine the maximal amount of devices to be spawned. */
list = mlx5_malloc(MLX5_MEM_ZERO,
- sizeof(struct mlx5_dev_spawn_data) *
- (np ? np : nd),
+ sizeof(struct mlx5_dev_spawn_data) * (np ? np : nd),
RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
if (!list) {
- DRV_LOG(ERR, "spawn data array allocation failure");
+ DRV_LOG(ERR, "Spawn data array allocation failure.");
rte_errno = ENOMEM;
ret = -rte_errno;
goto exit;
list[ns].bond_info = &bond_info;
list[ns].max_port = np;
list[ns].phys_port = i;
- list[ns].phys_dev = ibv_match[0];
+ list[ns].phys_dev_name = ibv_match[0]->name;
+ list[ns].ctx = ctx;
list[ns].eth_dev = NULL;
list[ns].pci_dev = pci_dev;
list[ns].cdev = cdev;
list[ns].pf_bond = bd;
- list[ns].ifindex = mlx5_nl_ifindex
- (nl_rdma,
- mlx5_os_get_dev_device_name
- (list[ns].phys_dev), i);
+ list[ns].ifindex = mlx5_nl_ifindex(nl_rdma,
+ ibv_match[0]->name,
+ i);
if (!list[ns].ifindex) {
/*
* No network interface index found for the
}
ret = -1;
if (nl_route >= 0)
- ret = mlx5_nl_switch_info
- (nl_route,
- list[ns].ifindex,
- &list[ns].info);
+ ret = mlx5_nl_switch_info(nl_route,
+ list[ns].ifindex,
+ &list[ns].info);
if (ret || (!list[ns].info.representor &&
!list[ns].info.master)) {
/*
* Netlink, let's try to perform the task
* with sysfs.
*/
- ret = mlx5_sysfs_switch_info
- (list[ns].ifindex,
- &list[ns].info);
+ ret = mlx5_sysfs_switch_info(list[ns].ifindex,
+ &list[ns].info);
}
if (!ret && bd >= 0) {
switch (list[ns].info.name_type) {
}
if (!ns) {
DRV_LOG(ERR,
- "unable to recognize master/representors"
- " on the IB device with multiple ports");
+ "Unable to recognize master/representors on the IB device with multiple ports.");
rte_errno = ENOENT;
ret = -rte_errno;
goto exit;
list[ns].bond_info = NULL;
list[ns].max_port = 1;
list[ns].phys_port = 1;
- list[ns].phys_dev = ibv_match[i];
+ list[ns].phys_dev_name = ibv_match[i]->name;
+ list[ns].ctx = ctx;
list[ns].eth_dev = NULL;
list[ns].pci_dev = pci_dev;
list[ns].cdev = cdev;
list[ns].ifindex = 0;
if (nl_rdma >= 0)
list[ns].ifindex = mlx5_nl_ifindex
- (nl_rdma,
- mlx5_os_get_dev_device_name
- (list[ns].phys_dev), 1);
+ (nl_rdma,
+ ibv_match[i]->name,
+ 1);
if (!list[ns].ifindex) {
char ifname[IF_NAMESIZE];
* Netlink, let's try to perform the task
* with sysfs.
*/
- ret = mlx5_sysfs_switch_info
- (list[ns].ifindex,
- &list[ns].info);
+ ret = mlx5_sysfs_switch_info(list[ns].ifindex,
+ &list[ns].info);
}
if (!ret && (list[ns].info.representor ^
list[ns].info.master)) {
!list[ns].info.representor &&
!list[ns].info.master) {
/*
- * Single IB device with
- * one physical port and
+ * Single IB device with one physical port and
* attached network device.
- * May be SRIOV is not enabled
- * or there is no representors.
+ * May be SRIOV is not enabled or there is no
+ * representors.
*/
- DRV_LOG(INFO, "no E-Switch support detected");
+ DRV_LOG(INFO, "No E-Switch support detected.");
ns++;
break;
}
}
if (!ns) {
DRV_LOG(ERR,
- "unable to recognize master/representors"
- " on the multiple IB devices");
+ "Unable to recognize master/representors on the multiple IB devices.");
rte_errno = ENOENT;
ret = -rte_errno;
goto exit;
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
static int
-mlx5_os_pci_probe(struct mlx5_common_device *cdev)
+mlx5_os_pci_probe(struct mlx5_common_device *cdev, void *ctx)
{
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
struct rte_eth_devargs eth_da = { .nb_ports = 0 };
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++) {
- ret = mlx5_os_pci_probe_pf(cdev, ð_da,
+ ret = mlx5_os_pci_probe_pf(cdev, ctx, ð_da,
eth_da.ports[p]);
if (ret)
break;
mlx5_net_remove(cdev);
}
} else {
- ret = mlx5_os_pci_probe_pf(cdev, ð_da, 0);
+ ret = mlx5_os_pci_probe_pf(cdev, ctx, ð_da, 0);
}
return ret;
}
/* Probe a single SF device on auxiliary bus, no representor support. */
static int
-mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev)
+mlx5_os_auxiliary_probe(struct mlx5_common_device *cdev, void *ctx)
{
struct rte_eth_devargs eth_da = { .nb_ports = 0 };
struct mlx5_dev_config config;
/* Init spawn data. */
spawn.max_port = 1;
spawn.phys_port = 1;
- spawn.phys_dev = mlx5_os_get_ibv_dev(dev);
- if (spawn.phys_dev == NULL)
- return -rte_errno;
+ spawn.ctx = ctx;
+ spawn.phys_dev_name = mlx5_os_get_ctx_device_name(ctx);
ret = mlx5_auxiliary_get_ifindex(dev->name);
if (ret < 0) {
DRV_LOG(ERR, "failed to get ethdev ifindex: %s", dev->name);
mlx5_os_net_probe(struct mlx5_common_device *cdev)
{
int ret;
+ void *ctx = NULL;
- if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ ret = mlx5_os_open_device(cdev, &ctx);
+ if (ret) {
+ DRV_LOG(ERR, "Fail to open device %s", cdev->dev->name);
+ return -rte_errno;
+ }
mlx5_pmd_socket_init();
+ }
ret = mlx5_init_once();
if (ret) {
DRV_LOG(ERR, "Unable to init PMD global data: %s",
strerror(rte_errno));
+ if (ctx != NULL)
+ claim_zero(mlx5_glue->close_device(ctx));
return -rte_errno;
}
if (mlx5_dev_is_pci(cdev->dev))
- return mlx5_os_pci_probe(cdev);
- else
- return mlx5_os_auxiliary_probe(cdev);
-}
-
-static int
-mlx5_config_doorbell_mapping_env(const struct mlx5_common_dev_config *config)
-{
- char *env;
- int value;
-
- MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
- /* Get environment variable to store. */
- env = getenv(MLX5_SHUT_UP_BF);
- value = env ? !!strcmp(env, "0") : MLX5_ARG_UNSET;
- if (config->dbnc == MLX5_ARG_UNSET)
- setenv(MLX5_SHUT_UP_BF, MLX5_SHUT_UP_BF_DEFAULT, 1);
+ return mlx5_os_pci_probe(cdev, ctx);
else
- setenv(MLX5_SHUT_UP_BF,
- config->dbnc == MLX5_TXDB_NCACHED ? "1" : "0", 1);
- return value;
-}
-
-static void
-mlx5_restore_doorbell_mapping_env(int value)
-{
- MLX5_ASSERT(rte_eal_process_type() == RTE_PROC_PRIMARY);
- /* Restore the original environment variable state. */
- if (value == MLX5_ARG_UNSET)
- unsetenv(MLX5_SHUT_UP_BF);
- else
- setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
+ return mlx5_os_auxiliary_probe(cdev, ctx);
}
/**
#endif /* HAVE_IBV_FLOW_DV_SUPPORT */
}
-/**
- * Function API to open IB device.
- *
- * This function calls the Linux glue APIs to open a device.
- *
- * @param[in] spawn
- * Pointer to the IB device attributes (name, port, etc).
- * @param[out] sh
- * Pointer to shared context structure.
- *
- * @return
- * 0 on success, a positive error value otherwise.
- */
-int
-mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- struct mlx5_dev_ctx_shared *sh)
-{
- int dbmap_env;
- int err = 0;
-
- pthread_mutex_init(&sh->txpp.mutex, NULL);
- /*
- * Configure environment variable "MLX5_BF_SHUT_UP"
- * before the device creation. The rdma_core library
- * checks the variable at device creation and
- * stores the result internally.
- */
- dbmap_env = mlx5_config_doorbell_mapping_env(&spawn->cdev->config);
- /* Try to open IB device with DV first, then usual Verbs. */
- errno = 0;
- sh->ctx = mlx5_glue->dv_open_device(spawn->phys_dev);
- if (sh->ctx) {
- sh->devx = 1;
- DRV_LOG(DEBUG, "DevX is supported");
- /* The device is created, no need for environment. */
- mlx5_restore_doorbell_mapping_env(dbmap_env);
- } else {
- /* The environment variable is still configured. */
- sh->ctx = mlx5_glue->open_device(spawn->phys_dev);
- err = errno ? errno : ENODEV;
- /*
- * The environment variable is not needed anymore,
- * all device creation attempts are completed.
- */
- mlx5_restore_doorbell_mapping_env(dbmap_env);
- if (!sh->ctx)
- return err;
- DRV_LOG(DEBUG, "DevX is NOT supported");
- err = 0;
- }
- if (!err && sh->ctx) {
- /* Hint libmlx5 to use PMD allocator for data plane resources */
- mlx5_glue->dv_set_context_attr(sh->ctx,
- MLX5DV_CTX_ATTR_BUF_ALLOCATORS,
- (void *)((uintptr_t)&(struct mlx5dv_ctx_allocators){
- .alloc = &mlx5_alloc_verbs_buf,
- .free = &mlx5_free_verbs_buf,
- .data = sh,
- }));
- }
- return err;
-}
-
/**
* Install shared asynchronous device events handler.
* This function is implemented to support event sharing
/* Search for IB context by device name. */
LIST_FOREACH(sh, &mlx5_dev_ctx_list, next) {
if (!strcmp(sh->ibdev_name,
- mlx5_os_get_dev_device_name(spawn->phys_dev))) {
+ mlx5_os_get_ctx_device_name(spawn->ctx))) {
sh->refcnt++;
goto exit;
}
rte_errno = ENOMEM;
goto exit;
}
+ pthread_mutex_init(&sh->txpp.mutex, NULL);
sh->numa_node = spawn->cdev->dev->numa_node;
sh->cdev = spawn->cdev;
+ sh->devx = sh->cdev->config.devx;
+ sh->ctx = spawn->ctx;
if (spawn->bond_info)
sh->bond = *spawn->bond_info;
- err = mlx5_os_open_device(spawn, sh);
- if (!sh->ctx)
- goto error;
err = mlx5_os_get_dev_attr(sh->ctx, &sh->device_attr);
if (err) {
DRV_LOG(DEBUG, "mlx5_os_get_dev_attr() failed");
uint32_t phys_port; /**< Device physical port index. */
int pf_bond; /**< bonding device PF index. < 0 - no bonding */
struct mlx5_switch_info info; /**< Switch information. */
- void *phys_dev; /**< Associated physical device. */
+ const char *phys_dev_name; /**< Name of physical device. */
+ void *ctx; /**< Associated physical device context. */
struct rte_eth_dev *eth_dev; /**< Associated Ethernet device. */
struct rte_pci_device *pci_dev; /**< Backend PCI device. */
struct mlx5_common_device *cdev; /**< Backend common device. */
struct rte_pci_driver;
int mlx5_os_get_dev_attr(void *ctx, struct mlx5_dev_attr *dev_attr);
void mlx5_os_free_shared_dr(struct mlx5_priv *priv);
-int mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- struct mlx5_dev_ctx_shared *sh);
int mlx5_os_get_pdn(void *pd, uint32_t *pdn);
int mlx5_os_net_probe(struct mlx5_common_device *cdev);
void mlx5_os_dev_shared_handler_install(struct mlx5_dev_ctx_shared *sh);
return -ENOTSUP;
}
-/**
- * Function API open device under Windows
- *
- * This function calls the Windows glue APIs to open a device.
- *
- * @param[in] spawn
- * Pointer to the device attributes (name, port, etc).
- * @param[out] sh
- * Pointer to shared context structure.
- *
- * @return
- * 0 on success, a positive error value otherwise.
- */
-int
-mlx5_os_open_device(const struct mlx5_dev_spawn_data *spawn,
- struct mlx5_dev_ctx_shared *sh)
-{
- int err = 0;
- struct mlx5_context *mlx5_ctx;
-
- pthread_mutex_init(&sh->txpp.mutex, NULL);
- /* Set numa node from pci probe */
- sh->numa_node = spawn->pci_dev->device.numa_node;
-
- /* Try to open device with DevX */
- rte_errno = 0;
- sh->ctx = mlx5_glue->open_device(spawn->phys_dev);
- if (!sh->ctx) {
- DRV_LOG(ERR, "open_device failed");
- err = errno;
- return err;
- }
- sh->devx = 1;
- mlx5_ctx = (struct mlx5_context *)sh->ctx;
- err = mlx5_glue->query_device(spawn->phys_dev, &mlx5_ctx->mlx5_dev);
- if (err)
- DRV_LOG(ERR, "Failed to query device context fields.");
- return err;
-}
-
/**
* DV flow counter mode detect and config.
*
return -ENOTSUP;
}
-/**
- * Detect if a devx_device_bdf object has identical DBDF values to the
- * rte_pci_addr found in bus/pci probing
- *
- * @param[in] devx_bdf
- * Pointer to the devx_device_bdf structure.
- * @param[in] addr
- * Pointer to the rte_pci_addr structure.
- *
- * @return
- * 1 on Device match, 0 on mismatch.
- */
-static int
-mlx5_match_devx_bdf_to_addr(struct devx_device_bdf *devx_bdf,
- struct rte_pci_addr *addr)
-{
- if (addr->domain != (devx_bdf->bus_id >> 8) ||
- addr->bus != (devx_bdf->bus_id & 0xff) ||
- addr->devid != devx_bdf->dev_id ||
- addr->function != devx_bdf->fnc_id) {
- return 0;
- }
- return 1;
-}
-
-/**
- * Detect if a devx_device_bdf object matches the rte_pci_addr
- * found in bus/pci probing
- * Compare both the Native/PF BDF and the raw_bdf representing a VF BDF.
- *
- * @param[in] devx_bdf
- * Pointer to the devx_device_bdf structure.
- * @param[in] addr
- * Pointer to the rte_pci_addr structure.
- *
- * @return
- * 1 on Device match, 0 on mismatch, rte_errno code on failure.
- */
-static int
-mlx5_match_devx_devices_to_addr(struct devx_device_bdf *devx_bdf,
- struct rte_pci_addr *addr)
-{
- int err;
- struct devx_device mlx5_dev;
-
- if (mlx5_match_devx_bdf_to_addr(devx_bdf, addr))
- return 1;
- /*
- * Didn't match on Native/PF BDF, could still match a VF BDF,
- * check it next.
- */
- err = mlx5_glue->query_device(devx_bdf, &mlx5_dev);
- if (err) {
- DRV_LOG(ERR, "query_device failed");
- rte_errno = err;
- return rte_errno;
- }
- if (mlx5_match_devx_bdf_to_addr(&mlx5_dev.raw_bdf, addr))
- return 1;
- return 0;
-}
-
-/**
- * Look for DevX device that match to given rte_device.
- *
- * @param dev
- * Pointer to the generic device.
- * @param orig_devx_list
- * Pointer to head of DevX devices list.
- * @param n
- * Number of devices in given DevX devices list.
- *
- * @return
- * A device match on success, NULL otherwise and rte_errno is set.
- */
-static struct devx_device_bdf *
-mlx5_os_get_devx_device(struct rte_device *dev,
- struct devx_device_bdf *orig_devx_list, int n)
-{
- struct devx_device_bdf *devx_list = orig_devx_list;
- struct devx_device_bdf *devx_match = NULL;
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
- struct rte_pci_addr *addr = &pci_dev->addr;
-
- while (n-- > 0) {
- int ret = mlx5_match_devx_devices_to_addr(devx_list, addr);
- if (!ret) {
- devx_list++;
- continue;
- }
- if (ret != 1) {
- rte_errno = ret;
- return NULL;
- }
- devx_match = devx_list;
- break;
- }
- if (devx_match == NULL) {
- /* No device matches, just complain and bail out. */
- DRV_LOG(WARNING,
- "No DevX device matches PCI device " PCI_PRI_FMT ","
- " is DevX Configured?",
- addr->domain, addr->bus, addr->devid, addr->function);
- rte_errno = ENOENT;
- }
- return devx_match;
-}
-
/**
* DPDK callback to register a PCI device.
*
mlx5_os_net_probe(struct mlx5_common_device *cdev)
{
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(cdev->dev);
- struct devx_device_bdf *devx_list;
- struct devx_device_bdf *devx_bdf_match;
struct mlx5_dev_spawn_data spawn = {
.pf_bond = -1,
.max_port = 1,
.dv_flow_en = 1,
.log_hp_size = MLX5_ARG_UNSET,
};
+ void *ctx;
int ret;
- int n;
uint32_t restore;
if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
DRV_LOG(ERR, "Secondary process is not supported on Windows.");
return -ENOTSUP;
}
+ ret = mlx5_os_open_device(cdev, &ctx);
+ if (ret) {
+ DRV_LOG(ERR, "Fail to open DevX device %s", cdev->dev->name);
+ return -rte_errno;
+ }
ret = mlx5_init_once();
if (ret) {
DRV_LOG(ERR, "unable to init PMD global data: %s",
strerror(rte_errno));
+ claim_zero(mlx5_glue->close_device(ctx));
return -rte_errno;
}
- errno = 0;
- devx_list = mlx5_glue->get_device_list(&n);
- if (devx_list == NULL) {
- rte_errno = errno ? errno : ENOSYS;
- DRV_LOG(ERR, "Cannot list devices, is DevX enabled?");
- return -rte_errno;
- }
- devx_bdf_match = mlx5_os_get_devx_device(cdev->dev, devx_list, n);
- if (devx_bdf_match == NULL) {
- ret = -rte_errno;
- goto exit;
- }
- spawn.phys_dev = devx_bdf_match;
+ spawn.ctx = ctx;
+ spawn.phys_dev_name = mlx5_os_get_ctx_device_name(ctx);
/* Device specific configuration. */
switch (pci_dev->id.device_id) {
case PCI_DEVICE_ID_MELLANOX_CONNECTX4VF:
}
spawn.eth_dev = mlx5_dev_spawn(cdev->dev, &spawn, &dev_config);
if (!spawn.eth_dev) {
- ret = -rte_errno;
- goto exit;
+ claim_zero(mlx5_glue->close_device(ctx));
+ return -rte_errno;
}
restore = spawn.eth_dev->data->dev_flags;
rte_eth_copy_pci_info(spawn.eth_dev, pci_dev);
/* Restore non-PCI flags cleared by the above call. */
spawn.eth_dev->data->dev_flags |= restore;
rte_eth_dev_probing_finish(spawn.eth_dev);
-exit:
- mlx5_glue->free_device_list(devx_list);
- return ret;
+ return 0;
}
/**