[PATCH libdrm 3/5] xf86drm: parse the separate sysfs files for vendor... info

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Emil Velikov <emil.velikov@xxxxxxxxxxxxx>

Up-to recently (patch should land in 4.10) the kernel did not expose the
PCI device revision field as a separate sysfs file.

Thus one needed too parse the config file to retrieve it. This in
itself wakes up the device, which in some cases can be quite slow.

To avoid that, just check for the separate files and fall-back to the
original if kernel is not new enough.

v3: rework alongside drmGetDevice[s]2

Cc: Michel Dänzer <michel@xxxxxxxxxxx>
Cc: Nicolai Hähnle <nhaehnle@xxxxxxxxx>
Cc: Mauro Santos <registo.mailling@xxxxxxxxx>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502
Signed-off-by: Emil Velikov <emil.velikov@xxxxxxxxxxxxx>
---
 xf86drm.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 4 deletions(-)

diff --git a/xf86drm.c b/xf86drm.c
index ddb8f9f..701cf29 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2946,11 +2946,49 @@ static int drmGetMaxNodeName(void)
            3 /* length of the node number */;
 }
 
-static int drmParsePciDeviceInfo(int maj, int min,
-                                 drmPciDeviceInfoPtr device,
-                                 uint32_t flags)
-{
 #ifdef __linux__
+static int parse_separate_sysfs_files(int maj, int min,
+                                      drmPciDeviceInfoPtr device)
+{
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+    static const char *attrs[] = {
+      "revision", /* Older kernels are missing the file, so check for it first */
+      "vendor",
+      "device",
+      "subsystem_vendor",
+      "subsystem_device",
+    };
+    char path[PATH_MAX + 1];
+    unsigned int data[ARRAY_SIZE(attrs)];
+    FILE *fp;
+    int ret;
+
+    for (unsigned i = 0; i < ARRAY_SIZE(attrs); i++) {
+        snprintf(path, PATH_MAX, "/sys/dev/char/%d:%d/device/%s", maj, min,
+                 attrs[i]);
+        fp = fopen(path, "r");
+        if (!fp)
+            return -errno;
+
+        ret = fscanf(fp, "%x", &data[i]);
+        fclose(fp);
+        if (ret != 1)
+            return -errno;
+
+    }
+
+    device->revision_id = data[0] & 0xff;
+    device->vendor_id = data[1] & 0xffff;
+    device->device_id = data[2] & 0xffff;
+    device->subvendor_id = data[3] & 0xffff;
+    device->subdevice_id = data[4] & 0xffff;
+
+    return 0;
+}
+
+static int parse_config_sysfs_file(int maj, int min,
+                                   drmPciDeviceInfoPtr device)
+{
     char path[PATH_MAX + 1];
     unsigned char config[64];
     int fd, ret;
@@ -2972,6 +3010,18 @@ static int drmParsePciDeviceInfo(int maj, int min,
     device->subdevice_id = config[46] | (config[47] << 8);
 
     return 0;
+}
+#endif
+
+static int drmParsePciDeviceInfo(int maj, int min,
+                                 drmPciDeviceInfoPtr device,
+                                 uint32_t flags)
+{
+#ifdef __linux__
+    if (parse_separate_sysfs_files(maj, min, device))
+        return parse_config_sysfs_file(maj, min, device);
+
+    return 0;
 #else
 #warning "Missing implementation of drmParsePciDeviceInfo"
     return -EINVAL;
-- 
2.10.2

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux