net/mlx5: select driver by class device argument
[dpdk.git] / drivers / common / mlx5 / mlx5_common.c
index 9c88a63..57d72b4 100644 (file)
@@ -5,6 +5,7 @@
 #include <dlfcn.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdio.h>
 
 #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;
+}
+
 #ifdef RTE_IBVERBS_LINK_DLOPEN
 
 /**