diff options
Diffstat (limited to 'src/vlib/linux/pci.c')
-rw-r--r-- | src/vlib/linux/pci.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c index 1e5ab67b25d..d968fe26695 100644 --- a/src/vlib/linux/pci.c +++ b/src/vlib/linux/pci.c @@ -55,6 +55,7 @@ #include <linux/vfio.h> #include <sys/eventfd.h> +#define SYSFS_DEVICES_PCI "/sys/devices/pci" 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 = @@ -383,6 +384,64 @@ done: return di; } +clib_error_t *__attribute__ ((weak)) +vlib_pci_get_device_root_bus (vlib_pci_addr_t *addr, vlib_pci_addr_t *root_bus) +{ + u8 *rel_path = 0, *abs_path = 0, *link_path = 0; + unformat_input_t input; + u32 fd = open (sysfs_pci_dev_path, O_RDONLY); + u32 size = 0; + u32 domain = 0, bus; + clib_error_t *err = NULL; + + if (fd < 0) + return clib_error_return_unix (0, "failed to open %s", sysfs_pci_dev_path); + + vec_alloc (rel_path, PATH_MAX); + vec_alloc (abs_path, PATH_MAX); + + link_path = + format (0, "%s/%U", sysfs_pci_dev_path, format_vlib_pci_addr, addr); + size = readlinkat (fd, (char *) link_path, (char *) rel_path, PATH_MAX); + if (size < 0) + { + err = clib_error_return_unix (0, "failed to read %s", rel_path); + goto done; + } + + rel_path[size] = '\0'; + vec_free (link_path); + + link_path = format (0, "%s/%s", sysfs_pci_dev_path, rel_path); + if (!realpath ((char *) link_path, (char *) abs_path)) + { + err = clib_error_return_unix (0, "failed to resolve %s", link_path); + goto done; + } + + unformat_init_string (&input, (char *) abs_path, + clib_strnlen ((char *) abs_path, PATH_MAX)); + + if (!unformat (&input, SYSFS_DEVICES_PCI "%x:%x/%s", &domain, &bus, + link_path)) + { + err = clib_error_return (0, "unknown input '%U'", format_unformat_error, + input); + goto done; + } + + root_bus->domain = domain; + root_bus->bus = bus; + +done: + vec_free (abs_path); + vec_free (link_path); + vec_free (rel_path); + close (fd); + + return err; +} + static int directory_exists (char *path) { |