[PATCH libpciaccess 1/2] linux sysfs: retrieve vendor, device... info via separate sysfs files

Emil Velikov emil.l.velikov at gmail.com
Thu Dec 1 18:17:35 UTC 2016


From: Emil Velikov <emil.velikov at collabora.com>

Currently the kernel does not expose the revision file. With that about
to change (due in 4.10) we can read all the information required from
separate files and avoid opening the config one.

The latter has the [negative] side effect of waking up the device, which
in some cases can be quite costly.

Cc: Adam Jackson <ajax at redhat.com>
Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
---
Adam, as suggested - here we fallback to config, if one is using an old
kernel.
---
 src/linux_sysfs.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index cd2713d..8055e8d 100644
--- a/src/linux_sysfs.c
+++ b/src/linux_sysfs.c
@@ -146,6 +146,56 @@ scan_sys_pci_filter( const struct dirent * d )
 }
 
 
+static int
+parse_separate_sysfs_files(struct pci_device * dev)
+{
+    static const char *attrs[] = {
+      "vendor",
+      "device",
+      "class",
+      "revision",
+      "subsystem_vendor",
+      "subsystem_device",
+    };
+    char name[256];
+    char resource[512];
+    uint64_t data[6];
+    int fd;
+    int i;
+
+    for (i = 0; i < 6; i++) {
+	snprintf(name, 255, "%s/%04x:%02x:%02x.%1u/%s",
+		 SYS_BUS_PCI,
+		 dev->domain,
+		 dev->bus,
+		 dev->dev,
+		 dev->func,
+		 attrs[i]);
+
+	fd = open(name, O_RDONLY | O_CLOEXEC);
+	if (fd == -1) {
+	    return errno;
+	}
+
+	read(fd, resource, 512);
+	resource[511] = '\0';
+
+	close(fd);
+
+	data[i] = strtoull(resource, NULL, 16);
+    }
+
+    dev->vendor_id = data[0] & 0xffff;
+    dev->device_id = data[1] & 0xffff;
+    dev->device_class = data[2] & 0xffffff;
+    dev->revision = data[3] & 0xff;
+    dev->subvendor_id = data[4] & 0xffff;
+    dev->subdevice_id = data[5] & 0xffff;
+
+    return 0;
+}
+
+
 int
 populate_entries( struct pci_system * p )
 {
@@ -178,6 +228,10 @@ populate_entries( struct pci_system * p )
 		device->base.func = func;
 
 
+		err = parse_separate_sysfs_files(& device->base);
+		if (!err)
+		    continue;
+
 		err = pci_device_linux_sysfs_read(& device->base, config, 0,
 						  48, & bytes);
 		if ((bytes == 48) && !err) {
-- 
2.10.2



More information about the xorg-devel mailing list