diff options
-rwxr-xr-x | src/plugins/dpdk/device/init.c | 2 | ||||
-rw-r--r-- | src/vlib/linux/pci.c | 55 | ||||
-rw-r--r-- | src/vpp/conf/startup.conf | 4 |
3 files changed, 58 insertions, 3 deletions
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index a6b6440f230..6041a3ca2a8 100755 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -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. diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c index 69dcdd0d760..62edcf4f8b6 100644 --- a/src/vlib/linux/pci.c +++ b/src/vlib/linux/pci.c @@ -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); diff --git a/src/vpp/conf/startup.conf b/src/vpp/conf/startup.conf index 304dd1fab3f..b18c6743869 100644 --- a/src/vpp/conf/startup.conf +++ b/src/vpp/conf/startup.conf @@ -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 |