pci: auto-detect right vfio/uio driver 01/9801/4
authorDamjan Marion <damarion@cisco.com>
Mon, 11 Dec 2017 14:55:56 +0000 (15:55 +0100)
committerDave Wallace <dwallacelf@gmail.com>
Thu, 14 Dec 2017 16:26:00 +0000 (16:26 +0000)
Change-Id: Ib4012ff598698924484525932d041988cc4c63f6
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/plugins/dpdk/device/init.c
src/vlib/linux/pci.c
src/vpp/conf/startup.conf

index a6b6440..6041a3c 100755 (executable)
@@ -1035,7 +1035,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
     }
 
   if (!conf->uio_driver_name)
-    conf->uio_driver_name = format (0, "uio_pci_generic%c", 0);
+    conf->uio_driver_name = format (0, "auto%c", 0);
 
   /*
    * Use 1G huge pages if available.
index 69dcdd0..62edcf4 100644 (file)
@@ -56,6 +56,8 @@
 
 static const char *sysfs_pci_dev_path = "/sys/bus/pci/devices";
 static const char *sysfs_pci_drv_path = "/sys/bus/pci/drivers";
+static char *sysfs_mod_vfio_noiommu =
+  "/sys/module/vfio/parameters/enable_unsafe_noiommu_mode";
 
 typedef struct
 {
@@ -314,6 +316,16 @@ done:
   return di;
 }
 
+static int
+directory_exists (char *path)
+{
+  struct stat s = { 0 };
+  if (stat (path, &s) == -1)
+    return 0;
+
+  return S_ISDIR (s.st_mode);
+}
+
 clib_error_t *
 vlib_pci_bind_to_uio (vlib_pci_addr_t * addr, char *uio_drv_name)
 {
@@ -331,6 +343,49 @@ vlib_pci_bind_to_uio (vlib_pci_addr_t * addr, char *uio_drv_name)
   if (error)
     return error;
 
+  if (strncmp ("auto", uio_drv_name, 5) == 0)
+    {
+      int vfio_pci_loaded = 0;
+
+      if (directory_exists ("/sys/module/vfio_pci"))
+       vfio_pci_loaded = 1;
+
+      if (di->iommu_group != -1)
+       {
+         /* device is bound to IOMMU group */
+         if (!vfio_pci_loaded)
+           {
+             error = clib_error_return (0, "Skipping PCI device %U: device "
+                                        "is bound to IOMMU group and "
+                                        "vfio-pci driver is not loaded",
+                                        format_vlib_pci_addr, addr);
+             goto done;
+           }
+         else
+           uio_drv_name = "vfio-pci";
+       }
+      else
+       {
+         /* device is not bound to IOMMU group so we have multiple options */
+         if (vfio_pci_loaded &&
+             (error = clib_sysfs_write (sysfs_mod_vfio_noiommu, "Y")) == 0)
+           uio_drv_name = "vfio-pci";
+         else if (directory_exists ("/sys/module/uio_pci_generic"))
+           uio_drv_name = "uio_pci_generic";
+         else if (directory_exists ("/sys/module/igb_uio"))
+           uio_drv_name = "igb_uio";
+         else
+           {
+             clib_error_free (error);
+             error = clib_error_return (0, "Skipping PCI device %U: missing "
+                                        "kernel VFIO or UIO driver",
+                                        format_vlib_pci_addr, addr);
+             goto done;
+           }
+         clib_error_free (error);
+       }
+    }
+
   s = format (s, "%v/driver%c", dev_dir_name, 0);
   driver_name = clib_sysfs_link_to_name ((char *) s);
   vec_reset_length (s);
index 304dd1f..b18c674 100644 (file)
@@ -105,8 +105,8 @@ cpu {
        # vdev eth_bond0,mode=1,slave=0000:02:00.0,slave=0000:03:00.0
        # vdev eth_bond1,mode=1,slave=0000:02:00.1,slave=0000:03:00.1
 
-       ## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci
-       ## and uio_pci_generic (default)
+       ## Change UIO driver used by VPP, Options are: igb_uio, vfio-pci,
+       ## uio_pci_generic or auto (default)
        # uio-driver vfio-pci
 
        ## Disable mutli-segment buffers, improves performance but