common/mlx5: fix build without dlopen option
[dpdk.git] / drivers / common / mlx5 / mlx5_common.c
index 9c88a63..9ea56f2 100644 (file)
@@ -2,9 +2,12 @@
  * 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
 
 /**
@@ -65,8 +211,6 @@ error:
  */
 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)
@@ -89,6 +233,8 @@ RTE_INIT_PRIO(mlx5_glue_init, CLASS)
        /* 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
@@ -158,13 +304,13 @@ RTE_INIT_PRIO(mlx5_glue_init, CLASS)
        }
        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)) {
@@ -176,8 +322,10 @@ RTE_INIT_PRIO(mlx5_glue_init, CLASS)
        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)");