summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-04-30 18:39:27 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-04-30 18:44:48 +0100
commitc864279de620a6e211b8a197dbdf9e3e1e2b60ab (patch)
tree818105bcc01e0713cded97034fded0e4bd9c0356
parentbff7ecde7bf3757e11ab4559212564e3f4919b89 (diff)
overlay: Parse /proc/interrupts in lieu of debugfs/i915_gem_interrupt
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>
-rw-r--r--overlay/gem-interrupts.c101
1 files changed, 73 insertions, 28 deletions
diff --git a/overlay/gem-interrupts.c b/overlay/gem-interrupts.c
index 15dc7919..48a36b85 100644
--- a/overlay/gem-interrupts.c
+++ b/overlay/gem-interrupts.c
@@ -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;