From 5714a49f14b93fc51185c6d37af101d24fc5dbd2 Mon Sep 17 00:00:00 2001 From: Ray Kinsella Date: Tue, 2 Nov 2021 13:33:44 +0000 Subject: [PATCH] vlib: retrieve the root bus of a given pci device Added a function to parse sysfs, determine the root bus & domain of a given pci device. Type: improvement Signed-off-by: Ray Kinsella Change-Id: I36778116ecaa2d591617450fe5ae0bdb46b4424b --- src/vlib/linux/pci.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vlib/pci/pci.c | 6 ++++++ src/vlib/pci/pci.h | 8 ++++--- 3 files changed, 70 insertions(+), 3 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 #include +#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) { diff --git a/src/vlib/pci/pci.c b/src/vlib/pci/pci.c index 18d93acbf08..5535eb1709c 100644 --- a/src/vlib/pci/pci.c +++ b/src/vlib/pci/pci.c @@ -61,6 +61,12 @@ vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr, return 0; } +clib_error_t *__attribute__ ((weak)) +vlib_pci_get_device_root_bus (vlib_pci_addr_t *addr, vlib_pci_addr_t *root_bus) +{ + return 0; +} + vlib_pci_addr_t * __attribute__ ((weak)) vlib_pci_get_all_dev_addrs () { return 0; diff --git a/src/vlib/pci/pci.h b/src/vlib/pci/pci.h index 01f7d5b9669..1dc4ce6ea36 100644 --- a/src/vlib/pci/pci.h +++ b/src/vlib/pci/pci.h @@ -96,9 +96,11 @@ typedef struct vlib_pci_device_info typedef u32 vlib_pci_dev_handle_t; -vlib_pci_device_info_t *vlib_pci_get_device_info (vlib_main_t * vm, - vlib_pci_addr_t * addr, - clib_error_t ** error); +vlib_pci_device_info_t *vlib_pci_get_device_info (vlib_main_t *vm, + vlib_pci_addr_t *addr, + clib_error_t **error); +clib_error_t *vlib_pci_get_device_root_bus (vlib_pci_addr_t *addr, + vlib_pci_addr_t *root_bus); vlib_pci_addr_t *vlib_pci_get_all_dev_addrs (); vlib_pci_addr_t *vlib_pci_get_addr (vlib_main_t * vm, vlib_pci_dev_handle_t h); -- 2.16.6