* Copyright 2019 Mellanox Technologies, Ltd
*/
-#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
+#include <stdio.h>
+#ifdef RTE_IBVERBS_LINK_DLOPEN
+#include <dlfcn.h>
+#endif
#include <rte_errno.h>
int mlx5_common_logtype;
+/**
+ * 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;
+}
+
+static int
+mlx5_class_check_handler(__rte_unused const char *key, const char *value,
+ void *opaque)
+{
+ enum mlx5_class *ret = opaque;
+
+ if (strcmp(value, "vdpa") == 0) {
+ *ret = MLX5_CLASS_VDPA;
+ } else if (strcmp(value, "net") == 0) {
+ *ret = MLX5_CLASS_NET;
+ } else {
+ DRV_LOG(ERR, "Invalid mlx5 class %s. Maybe typo in device"
+ " class argument setting?", value);
+ *ret = MLX5_CLASS_INVALID;
+ }
+ return 0;
+}
+
+enum mlx5_class
+mlx5_class_get(struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+ const char *key = MLX5_CLASS_ARG_NAME;
+ enum mlx5_class ret = MLX5_CLASS_NET;
+
+ if (devargs == NULL)
+ return ret;
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL)
+ return ret;
+ if (rte_kvargs_count(kvlist, key))
+ rte_kvargs_process(kvlist, key, mlx5_class_check_handler, &ret);
+ rte_kvargs_free(kvlist);
+ return ret;
+}
+
+/**
+ * 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;
+}
+
#ifdef RTE_IBVERBS_LINK_DLOPEN
/**
*/
RTE_INIT_PRIO(mlx5_glue_init, CLASS)
{
- void *handle = NULL;
-
/* Initialize common log type. */
mlx5_common_logtype = rte_log_register("pmd.common.mlx5");
if (mlx5_common_logtype >= 0)
/* The glue initialization was done earlier by mlx5 common library. */
#ifdef RTE_IBVERBS_LINK_DLOPEN
char glue_path[sizeof(RTE_EAL_PMD_PATH) - 1 + sizeof("-glue")];
+ void *handle = NULL;
+
const char *path[] = {
/*
* A basic security check is necessary before trusting
}
mlx5_glue = *sym;
#endif /* RTE_IBVERBS_LINK_DLOPEN */
-#ifndef NDEBUG
+#ifdef RTE_LIBRTE_MLX5_DEBUG
/* Glue structure must not contain any NULL pointers. */
{
unsigned int i;
for (i = 0; i != sizeof(*mlx5_glue) / sizeof(void *); ++i)
- assert(((const void *const *)mlx5_glue)[i]);
+ MLX5_ASSERT(((const void *const *)mlx5_glue)[i]);
}
#endif
if (strcmp(mlx5_glue->version, MLX5_GLUE_VERSION)) {
mlx5_glue->fork_init();
return;
glue_error:
+#ifdef RTE_IBVERBS_LINK_DLOPEN
if (handle)
dlclose(handle);
+#endif
DRV_LOG(WARNING, "Cannot initialize MLX5 common due to missing"
" run-time dependency on rdma-core libraries (libibverbs,"
" libmlx5)");