From f839b9599f863fa5bb1a6a6c24bbb621b7a1b4c9 Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Tue, 12 Oct 2021 14:31:31 -0700 Subject: [PATCH] loader: Avoid enumerating drm devices just to get an fd's PCI ID. Cuts 1/3 of the runtime of the VA-API unit tests (which do a separate pipe-loader init per test) on radeonsi on my system by not faffing around in sysfs so much. Reviewed-by: Adam Jackson Reviewed-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/loader/loader.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/loader/loader.c b/src/loader/loader.c index 58727155075..945c99fb4bf 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -47,6 +47,7 @@ #include #include #include "loader.h" +#include "util/os_file.h" #ifdef HAVE_LIBDRM #include @@ -407,10 +408,52 @@ drm_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) } #endif +#ifdef __linux__ +static int loader_get_linux_pci_field(int maj, int min, const char *field) +{ + char path[PATH_MAX + 1]; + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device/%s", maj, min, field); + + char *field_str = os_read_file(path, NULL); + if (!field_str) { + /* Probably non-PCI device. */ + return 0; + } + + int value = (int)strtoll(field_str, NULL, 16); + free(field_str); + + return value; +} + +static bool +loader_get_linux_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) +{ + struct stat sbuf; + if (fstat(fd, &sbuf) != 0) { + log_(_LOADER_DEBUG, "MESA-LOADER: failed to fstat fd\n"); + return false; + } + + int maj = major(sbuf.st_rdev); + int min = minor(sbuf.st_rdev); + + *vendor_id = loader_get_linux_pci_field(maj, min, "vendor"); + *chip_id = loader_get_linux_pci_field(maj, min, "device"); + + return *vendor_id && *chip_id; +} +#endif /* __linux__ */ bool loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) { +#ifdef __linux__ + /* Implementation without causing full enumeration of DRM devices. */ + if (loader_get_linux_pci_id_for_fd(fd, vendor_id, chip_id)) + return true; +#endif + #if HAVE_LIBDRM return drm_get_pci_id_for_fd(fd, vendor_id, chip_id); #endif