overlay: Parse /proc/interrupts in lieu of debugfs/i915_gem_interrupt
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 30 Apr 2014 17:39:27 +0000 (18:39 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 30 Apr 2014 17:44:48 +0000 (18:44 +0100)
So the interrupt counter was removed from i915_gem_interrupt, and if we
do not have the perf API available, we therefore need to read it from
/proc/interrupts instead.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
overlay/gem-interrupts.c

index 15dc791..48a36b8 100644 (file)
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "gem-interrupts.h"
 #include "debugfs.h"
@@ -48,16 +49,77 @@ static int perf_open(void)
        return perf_event_open(&attr, -1, 0, -1, 0);
 }
 
-static int debugfs_open(void)
+static long long debugfs_read(void)
 {
-       char buf[1024];
-       struct stat st;
+       char buf[8192], *b;
+       int fd, len;
 
        sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
-       if (stat(buf, &st))
-               return errno;
+       fd = open(buf, 0);
+       if (fd < 0)
+               return -1;
 
-       return 0;
+       len = read(fd, buf, sizeof(buf)-1);
+       close(fd);
+
+       if (len < 0)
+               return -1;
+
+       buf[len] = '\0';
+
+       b = strstr(buf, "Interrupts received:");
+       if (b == NULL)
+               return -1;
+
+       return strtoull(b + sizeof("Interrupts received:"), 0, 0);
+}
+
+static long long procfs_read(void)
+{
+       char buf[8192], *b;
+       int fd, len;
+       unsigned long long val;
+
+/* 44:         51      42446          0          0   PCI-MSI-edge      i915*/
+       fd = open("/proc/interrupts", 0);
+       if (fd < 0)
+               return -1;
+
+       len = read(fd, buf, sizeof(buf)-1);
+       close(fd);
+
+       if (len < 0)
+               return -1;
+
+       buf[len] = '\0';
+
+       b = strstr(buf, "i915");
+       if (b == NULL)
+               return -1;
+       while (*--b != ':')
+               ;
+
+       val = 0;
+       do {
+               while (isspace(*++b))
+                       ;
+               if (!isdigit(*b))
+                       break;
+
+               val += strtoull(b, &b, 0);
+       } while(1);
+
+       return val;
+}
+
+static long long interrupts_read(void)
+{
+       long long val;
+
+       val = debugfs_read();
+       if (val < 0)
+               val = procfs_read();
+       return val;
 }
 
 int gem_interrupts_init(struct gem_interrupts *irqs)
@@ -65,8 +127,8 @@ int gem_interrupts_init(struct gem_interrupts *irqs)
        memset(irqs, 0, sizeof(*irqs));
 
        irqs->fd = perf_open();
-       if (irqs->fd < 0)
-               irqs->error = debugfs_open();
+       if (irqs->fd < 0 && interrupts_read() < 0)
+               irqs->error = ENODEV;
 
        return irqs->error;
 }
@@ -80,26 +142,9 @@ int gem_interrupts_update(struct gem_interrupts *irqs)
                return irqs->error;
 
        if (irqs->fd < 0) {
-               char buf[8192], *b;
-               int fd, len;
-
-               sprintf(buf, "%s/i915_gem_interrupt", debugfs_dri_path);
-               fd = open(buf, 0);
-               if (fd < 0)
-                       return irqs->error = errno;
-               len = read(fd, buf, sizeof(buf)-1);
-               close(fd);
-
-               if (len < 0)
-                       return irqs->error = errno;
-
-               buf[len] = '\0';
-
-               b = strstr(buf, "Interrupts received:");
-               if (b == NULL)
-                       return irqs->error = ENOENT;
-
-               val = strtoull(b + sizeof("Interrupts received:"), 0, 0);
+               val = interrupts_read();
+               if (val < 0)
+                       return irqs->error = ENODEV;
        } else {
                if (read(irqs->fd, &val, sizeof(val)) < 0)
                        return irqs->error = errno;